diff options
Diffstat (limited to '')
-rw-r--r-- | src/modules/module-session-manager/protocol-native.c | 3083 |
1 files changed, 3083 insertions, 0 deletions
diff --git a/src/modules/module-session-manager/protocol-native.c b/src/modules/module-session-manager/protocol-native.c new file mode 100644 index 0000000..6981252 --- /dev/null +++ b/src/modules/module-session-manager/protocol-native.c @@ -0,0 +1,3083 @@ +/* PipeWire + * + * Copyright © 2019 Collabora Ltd. + * @author George Kiagiadakis <george.kiagiadakis@collabora.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <pipewire/pipewire.h> + +#include <spa/utils/result.h> +#include <spa/pod/builder.h> +#include <spa/pod/parser.h> + +#include <pipewire/extensions/session-manager.h> +#include <pipewire/extensions/protocol-native.h> + +#define MAX_DICT 1024 +#define MAX_PARAMS 4096 +#define MAX_PARAM_INFO 128 + +static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict) +{ + struct spa_pod_frame f; + uint32_t n_items; + uint32_t i; + + n_items = dict ? dict->n_items : 0; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, SPA_POD_Int(n_items), NULL); + for (i = 0; i < n_items; i++) { + spa_pod_builder_add(b, + SPA_POD_String(dict->items[i].key), + SPA_POD_String(dict->items[i].value), + NULL); + } + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define parse_dict(p, f, dict) \ +do { \ + uint32_t i; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, SPA_POD_Int(&(dict)->n_items), NULL) < 0) \ + return -EINVAL; \ + \ + if ((dict)->n_items > 0) { \ + if ((dict)->n_items > MAX_DICT) \ + return -ENOSPC; \ + (dict)->items = alloca((dict)->n_items * sizeof(struct spa_dict_item)); \ + for (i = 0; i < (dict)->n_items; i++) { \ + if (spa_pod_parser_get(p, \ + SPA_POD_String(&(dict)->items[i].key), \ + SPA_POD_String(&(dict)->items[i].value), \ + NULL) < 0) \ + return -EINVAL; \ + } \ + } \ + spa_pod_parser_pop(p, f); \ +} while(0) + +static void push_param_infos(struct spa_pod_builder *b, uint32_t n_params, + const struct spa_param_info *params) +{ + struct spa_pod_frame f; + uint32_t i; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, SPA_POD_Int(n_params), NULL); + for (i = 0; i < n_params; i++) { + spa_pod_builder_add(b, + SPA_POD_Id(params[i].id), + SPA_POD_Int(params[i].flags), + NULL); + } + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define parse_param_infos(p, f, n_params_p, params_p) \ +do { \ + uint32_t i; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, SPA_POD_Int(n_params_p), NULL) < 0) \ + return -EINVAL; \ + \ + if (*(n_params_p) > 0) { \ + if (*(n_params_p) > MAX_PARAM_INFO) \ + return -ENOSPC; \ + *(params_p) = alloca(*(n_params_p) * sizeof(struct spa_param_info)); \ + for (i = 0; i < *(n_params_p); i++) { \ + if (spa_pod_parser_get(p, \ + SPA_POD_Id(&(*(params_p))[i].id), \ + SPA_POD_Int(&(*(params_p))[i].flags), \ + NULL) < 0) \ + return -EINVAL; \ + } \ + } \ + spa_pod_parser_pop(p, f); \ +} while(0) + +/*********************************************** + * INFO STRUCTURES + ***********************************************/ + +static void +marshal_pw_session_info(struct spa_pod_builder *b, + const struct pw_session_info *info) +{ + struct spa_pod_frame f; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(info->version), + SPA_POD_Int(info->id), + SPA_POD_Long(info->change_mask), + NULL); + push_dict(b, info->props); + push_param_infos(b, info->n_params, info->params); + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define demarshal_pw_session_info(p, f, info) \ +do { \ + struct spa_pod_frame sub_f; \ + uint32_t version; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, \ + SPA_POD_Int(&version), \ + SPA_POD_Int(&(info)->id), \ + SPA_POD_Long(&(info)->change_mask), \ + NULL) < 0) \ + return -EINVAL; \ + \ + (info)->change_mask &= PW_SESSION_CHANGE_MASK_ALL; \ + \ + parse_dict(p, &sub_f, (info)->props); \ + parse_param_infos(p, &sub_f, &(info)->n_params, &(info)->params); \ + \ + spa_pod_parser_pop(p, f); \ +} while(0) + +static void +marshal_pw_endpoint_info(struct spa_pod_builder *b, + const struct pw_endpoint_info *info) +{ + struct spa_pod_frame f; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(info->version), + SPA_POD_Int(info->id), + SPA_POD_String(info->name), + SPA_POD_String(info->media_class), + SPA_POD_Int(info->direction), + SPA_POD_Int(info->flags), + SPA_POD_Long(info->change_mask), + SPA_POD_Int(info->n_streams), + SPA_POD_Int(info->session_id), + NULL); + push_dict(b, info->props); + push_param_infos(b, info->n_params, info->params); + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define demarshal_pw_endpoint_info(p, f, info) \ +do { \ + struct spa_pod_frame sub_f; \ + uint32_t version; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, \ + SPA_POD_Int(&version), \ + SPA_POD_Int(&(info)->id), \ + SPA_POD_String(&(info)->name), \ + SPA_POD_String(&(info)->media_class), \ + SPA_POD_Int(&(info)->direction), \ + SPA_POD_Int(&(info)->flags), \ + SPA_POD_Long(&(info)->change_mask), \ + SPA_POD_Int(&(info)->n_streams), \ + SPA_POD_Int(&(info)->session_id), \ + NULL) < 0) \ + return -EINVAL; \ + \ + (info)->change_mask &= PW_ENDPOINT_CHANGE_MASK_ALL; \ + \ + parse_dict(p, &sub_f, (info)->props); \ + parse_param_infos(p, &sub_f, &(info)->n_params, &(info)->params); \ + \ + spa_pod_parser_pop(p, f); \ +} while(0) + +static void +marshal_pw_endpoint_stream_info(struct spa_pod_builder *b, + const struct pw_endpoint_stream_info *info) +{ + struct spa_pod_frame f; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(info->version), + SPA_POD_Int(info->id), + SPA_POD_Int(info->endpoint_id), + SPA_POD_String(info->name), + SPA_POD_Long(info->change_mask), + SPA_POD_Pod(info->link_params), + NULL); + push_dict(b, info->props); + push_param_infos(b, info->n_params, info->params); + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define demarshal_pw_endpoint_stream_info(p, f, info) \ +do { \ + struct spa_pod_frame sub_f; \ + uint32_t version; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, \ + SPA_POD_Int(&version), \ + SPA_POD_Int(&(info)->id), \ + SPA_POD_Int(&(info)->endpoint_id), \ + SPA_POD_String(&(info)->name), \ + SPA_POD_Long(&(info)->change_mask), \ + SPA_POD_Pod(&(info)->link_params), \ + NULL) < 0) \ + return -EINVAL; \ + \ + (info)->change_mask &= PW_ENDPOINT_STREAM_CHANGE_MASK_ALL; \ + \ + parse_dict(p, &sub_f, (info)->props); \ + parse_param_infos(p, &sub_f, &(info)->n_params, &(info)->params); \ + \ + spa_pod_parser_pop(p, f); \ +} while(0) + +static void +marshal_pw_endpoint_link_info(struct spa_pod_builder *b, + const struct pw_endpoint_link_info *info) +{ + struct spa_pod_frame f; + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(info->version), + SPA_POD_Int(info->id), + SPA_POD_Int(info->session_id), + SPA_POD_Int(info->output_endpoint_id), + SPA_POD_Int(info->output_stream_id), + SPA_POD_Int(info->input_endpoint_id), + SPA_POD_Int(info->input_stream_id), + SPA_POD_Long(info->change_mask), + SPA_POD_Int(info->state), + SPA_POD_String(info->error), + NULL); + push_dict(b, info->props); + push_param_infos(b, info->n_params, info->params); + spa_pod_builder_pop(b, &f); +} + +/* macro because of alloca() */ +#define demarshal_pw_endpoint_link_info(p, f, info) \ +do { \ + struct spa_pod_frame sub_f; \ + uint32_t version; \ + \ + if (spa_pod_parser_push_struct(p, f) < 0 || \ + spa_pod_parser_get(p, \ + SPA_POD_Int(&version), \ + SPA_POD_Int(&(info)->id), \ + SPA_POD_Int(&(info)->session_id), \ + SPA_POD_Int(&(info)->output_endpoint_id), \ + SPA_POD_Int(&(info)->output_stream_id), \ + SPA_POD_Int(&(info)->input_endpoint_id), \ + SPA_POD_Int(&(info)->input_stream_id), \ + SPA_POD_Long(&(info)->change_mask), \ + SPA_POD_Int(&(info)->state), \ + SPA_POD_String(&(info)->error), \ + NULL) < 0) \ + return -EINVAL; \ + \ + (info)->change_mask &= PW_ENDPOINT_LINK_CHANGE_MASK_ALL; \ + \ + parse_dict(p, &sub_f, (info)->props); \ + parse_param_infos(p, &sub_f, &(info)->n_params, &(info)->params); \ + \ + spa_pod_parser_pop(p, f); \ +} while(0) + + +/*********************************************** + * COMMON + ***********************************************/ + +static int demarshal_add_listener_enotsup(void *object, + const struct pw_protocol_native_message *msg) +{ + return -ENOTSUP; +} + +/*********************************************** + * CLIENT ENDPOINT + ***********************************************/ + +static int client_endpoint_marshal_set_session_id (void *object, uint32_t id) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_CLIENT_ENDPOINT_EVENT_SET_SESSION_ID, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(id)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_endpoint_marshal_set_param (void *object, + 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_ENDPOINT_EVENT_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_endpoint_marshal_stream_set_param (void *object, + uint32_t stream_id, 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_ENDPOINT_EVENT_STREAM_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(stream_id), + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_endpoint_marshal_create_link (void *object, + const struct spa_dict *props) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_CLIENT_ENDPOINT_EVENT_CREATE_LINK, NULL); + + push_dict(b, props); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_endpoint_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_client_endpoint_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int client_endpoint_marshal_update(void *object, + uint32_t change_mask, + uint32_t n_params, + const struct spa_pod **params, + const struct pw_endpoint_info *info) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + struct spa_pod_frame f; + uint32_t i; + + b = pw_protocol_native_begin_proxy(proxy, + PW_CLIENT_ENDPOINT_METHOD_UPDATE, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(change_mask), + SPA_POD_Int(n_params), + NULL); + + for (i = 0; i < n_params; i++) + spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL); + + if (info) + marshal_pw_endpoint_info(b, info); + else + spa_pod_builder_add(b, SPA_POD_Pod(NULL), NULL); + + spa_pod_builder_pop(b, &f); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int client_endpoint_marshal_stream_update(void *object, + uint32_t stream_id, + uint32_t change_mask, + uint32_t n_params, + const struct spa_pod **params, + const struct pw_endpoint_stream_info *info) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + struct spa_pod_frame f; + uint32_t i; + + b = pw_protocol_native_begin_proxy(proxy, + PW_CLIENT_ENDPOINT_METHOD_STREAM_UPDATE, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(stream_id), + SPA_POD_Int(change_mask), + SPA_POD_Int(n_params), + NULL); + + for (i = 0; i < n_params; i++) + spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL); + + if (info) + marshal_pw_endpoint_stream_info(b, info); + else + spa_pod_builder_add(b, SPA_POD_Pod(NULL), NULL); + + spa_pod_builder_pop(b, &f); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int client_endpoint_demarshal_set_session_id(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&id)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_endpoint_events, + set_session_id, 0, id); +} + +static int client_endpoint_demarshal_set_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, flags; + const struct spa_pod *param = NULL; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_PodObject(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_endpoint_events, + set_param, 0, id, flags, param); +} + +static int client_endpoint_demarshal_stream_set_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t stream_id, id, flags; + const struct spa_pod *param = NULL; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&stream_id), + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_PodObject(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_endpoint_events, + stream_set_param, 0, stream_id, id, flags, param); +} + +static int client_endpoint_demarshal_create_link(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + + spa_pod_parser_init(&prs, msg->data, msg->size); + + parse_dict(&prs, &f, &props); + + return pw_proxy_notify(proxy, struct pw_client_endpoint_events, + create_link, 0, &props); +} + +static int client_endpoint_demarshal_update(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs[2]; + struct spa_pod_frame f[2]; + uint32_t change_mask, n_params; + const struct spa_pod **params = NULL; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_info info = { .props = &props }, *infop = NULL; + struct spa_pod *ipod; + uint32_t i; + + spa_pod_parser_init(&prs[0], msg->data, msg->size); + if (spa_pod_parser_push_struct(&prs[0], &f[0]) < 0 || + spa_pod_parser_get(&prs[0], + SPA_POD_Int(&change_mask), + SPA_POD_Int(&n_params), NULL) < 0) + return -EINVAL; + + if (n_params > MAX_PARAMS) + return -ENOSPC; + if (n_params > 0) + params = alloca(n_params * sizeof(struct spa_pod *)); + for (i = 0; i < n_params; i++) + if (spa_pod_parser_get(&prs[0], + SPA_POD_PodObject(¶ms[i]), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_get(&prs[0], SPA_POD_PodStruct(&ipod), NULL) < 0) + return -EINVAL; + if (ipod) { + infop = &info; + spa_pod_parser_pod(&prs[1], ipod); + demarshal_pw_endpoint_info(&prs[1], &f[1], infop); + } + + return pw_resource_notify(resource, struct pw_client_endpoint_methods, + update, 0, change_mask, n_params, params, infop); +} + +static int client_endpoint_demarshal_stream_update(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs[2]; + struct spa_pod_frame f[2]; + uint32_t stream_id, change_mask, n_params; + const struct spa_pod **params = NULL; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_stream_info info = { .props = &props }, *infop = NULL; + struct spa_pod *ipod; + uint32_t i; + + spa_pod_parser_init(&prs[0], msg->data, msg->size); + if (spa_pod_parser_push_struct(&prs[0], &f[0]) < 0 || + spa_pod_parser_get(&prs[0], + SPA_POD_Int(&stream_id), + SPA_POD_Int(&change_mask), + SPA_POD_Int(&n_params), NULL) < 0) + return -EINVAL; + + if (n_params > MAX_PARAMS) + return -ENOSPC; + if (n_params > 0) + params = alloca(n_params * sizeof(struct spa_pod *)); + for (i = 0; i < n_params; i++) + if (spa_pod_parser_get(&prs[0], + SPA_POD_PodObject(¶ms[i]), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_get(&prs[0], SPA_POD_PodStruct(&ipod), NULL) < 0) + return -EINVAL; + if (ipod) { + infop = &info; + spa_pod_parser_pod(&prs[1], ipod); + demarshal_pw_endpoint_stream_info(&prs[1], &f[1], infop); + } + + return pw_resource_notify(resource, struct pw_client_endpoint_methods, + stream_update, 0, stream_id, change_mask, n_params, params, infop); +} + +static const struct pw_client_endpoint_events pw_protocol_native_client_endpoint_event_marshal = { + PW_VERSION_CLIENT_ENDPOINT_EVENTS, + .set_session_id = client_endpoint_marshal_set_session_id, + .set_param = client_endpoint_marshal_set_param, + .stream_set_param = client_endpoint_marshal_stream_set_param, + .create_link = client_endpoint_marshal_create_link, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_client_endpoint_event_demarshal[PW_CLIENT_ENDPOINT_EVENT_NUM] = +{ + [PW_CLIENT_ENDPOINT_EVENT_SET_SESSION_ID] = { client_endpoint_demarshal_set_session_id, 0 }, + [PW_CLIENT_ENDPOINT_EVENT_SET_PARAM] = { client_endpoint_demarshal_set_param, 0 }, + [PW_CLIENT_ENDPOINT_EVENT_STREAM_SET_PARAM] = { client_endpoint_demarshal_stream_set_param, 0 }, + [PW_CLIENT_ENDPOINT_EVENT_CREATE_LINK] = { client_endpoint_demarshal_create_link, 0 }, +}; + +static const struct pw_client_endpoint_methods pw_protocol_native_client_endpoint_method_marshal = { + PW_VERSION_CLIENT_ENDPOINT_METHODS, + .add_listener = client_endpoint_marshal_add_listener, + .update = client_endpoint_marshal_update, + .stream_update = client_endpoint_marshal_stream_update, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_client_endpoint_method_demarshal[PW_CLIENT_ENDPOINT_METHOD_NUM] = +{ + [PW_CLIENT_ENDPOINT_METHOD_ADD_LISTENER] = { NULL, 0 }, + [PW_CLIENT_ENDPOINT_METHOD_UPDATE] = { client_endpoint_demarshal_update, 0 }, + [PW_CLIENT_ENDPOINT_METHOD_STREAM_UPDATE] = { client_endpoint_demarshal_stream_update, 0 }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_client_endpoint_marshal = { + PW_TYPE_INTERFACE_ClientEndpoint, + PW_VERSION_CLIENT_ENDPOINT, + 0, + PW_CLIENT_ENDPOINT_METHOD_NUM, + PW_CLIENT_ENDPOINT_EVENT_NUM, + &pw_protocol_native_client_endpoint_method_marshal, + &pw_protocol_native_client_endpoint_method_demarshal, + &pw_protocol_native_client_endpoint_event_marshal, + &pw_protocol_native_client_endpoint_event_demarshal, +}; + +/*********************************************** + * CLIENT SESSION + ***********************************************/ + +static int client_session_marshal_set_param (void *data, + uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_CLIENT_SESSION_EVENT_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_session_marshal_link_set_param (void *data, + uint32_t link_id, uint32_t id, + uint32_t flags, const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_CLIENT_SESSION_EVENT_LINK_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(link_id), + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_session_marshal_link_request_state (void *data, + uint32_t link_id, uint32_t state) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_CLIENT_SESSION_EVENT_LINK_REQUEST_STATE, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(link_id), + SPA_POD_Int(state)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int client_session_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_client_session_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int client_session_marshal_update(void *object, + uint32_t change_mask, + uint32_t n_params, + const struct spa_pod **params, + const struct pw_session_info *info) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + struct spa_pod_frame f; + uint32_t i; + + b = pw_protocol_native_begin_proxy(proxy, + PW_CLIENT_SESSION_METHOD_UPDATE, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(change_mask), + SPA_POD_Int(n_params), + NULL); + + for (i = 0; i < n_params; i++) + spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL); + + if (info) + marshal_pw_session_info(b, info); + else + spa_pod_builder_add(b, SPA_POD_Pod(NULL), NULL); + + spa_pod_builder_pop(b, &f); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int client_session_marshal_link_update(void *object, + uint32_t link_id, + uint32_t change_mask, + uint32_t n_params, + const struct spa_pod **params, + const struct pw_endpoint_link_info *info) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + struct spa_pod_frame f; + uint32_t i; + + b = pw_protocol_native_begin_proxy(proxy, + PW_CLIENT_SESSION_METHOD_LINK_UPDATE, NULL); + + spa_pod_builder_push_struct(b, &f); + spa_pod_builder_add(b, + SPA_POD_Int(link_id), + SPA_POD_Int(change_mask), + SPA_POD_Int(n_params), + NULL); + + for (i = 0; i < n_params; i++) + spa_pod_builder_add(b, SPA_POD_Pod(params[i]), NULL); + + if (info) + marshal_pw_endpoint_link_info(b, info); + else + spa_pod_builder_add(b, SPA_POD_Pod(NULL), NULL); + + spa_pod_builder_pop(b, &f); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int client_session_demarshal_set_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, flags; + const struct spa_pod *param = NULL; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_PodObject(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_session_events, + set_param, 0, id, flags, param); +} + +static int client_session_demarshal_link_set_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t link_id, id, flags; + const struct spa_pod *param = NULL; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&link_id), + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_PodObject(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_session_events, + link_set_param, 0, link_id, id, flags, param); +} + +static int client_session_demarshal_link_request_state(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t link_id, state; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&link_id), + SPA_POD_Int(&state)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_client_session_events, + link_request_state, 0, link_id, state); +} + +static int client_session_demarshal_update(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs[2]; + struct spa_pod_frame f[2]; + uint32_t change_mask, n_params; + const struct spa_pod **params = NULL; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_session_info info = { .props = &props }, *infop = NULL; + struct spa_pod *ipod; + uint32_t i; + + spa_pod_parser_init(&prs[0], msg->data, msg->size); + if (spa_pod_parser_push_struct(&prs[0], &f[0]) < 0 || + spa_pod_parser_get(&prs[0], + SPA_POD_Int(&change_mask), + SPA_POD_Int(&n_params), NULL) < 0) + return -EINVAL; + + if (n_params > MAX_PARAMS) + return -ENOSPC; + if (n_params > 0) + params = alloca(n_params * sizeof(struct spa_pod *)); + for (i = 0; i < n_params; i++) + if (spa_pod_parser_get(&prs[0], + SPA_POD_PodObject(¶ms[i]), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_get(&prs[0], SPA_POD_PodStruct(&ipod), NULL) < 0) + return -EINVAL; + if (ipod) { + infop = &info; + spa_pod_parser_pod(&prs[1], ipod); + demarshal_pw_session_info(&prs[1], &f[1], infop); + } + + return pw_resource_notify(resource, struct pw_client_session_methods, + update, 0, change_mask, n_params, params, infop); +} + +static int client_session_demarshal_link_update(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs[2]; + struct spa_pod_frame f[2]; + uint32_t link_id, change_mask, n_params; + const struct spa_pod **params = NULL; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_link_info info = { .props = &props }, *infop = NULL; + struct spa_pod *ipod; + uint32_t i; + + spa_pod_parser_init(&prs[0], msg->data, msg->size); + if (spa_pod_parser_push_struct(&prs[0], &f[0]) < 0 || + spa_pod_parser_get(&prs[0], + SPA_POD_Int(&link_id), + SPA_POD_Int(&change_mask), + SPA_POD_Int(&n_params), NULL) < 0) + return -EINVAL; + + if (n_params > MAX_PARAMS) + return -ENOSPC; + if (n_params > 0) + params = alloca(n_params * sizeof(struct spa_pod *)); + for (i = 0; i < n_params; i++) + if (spa_pod_parser_get(&prs[0], + SPA_POD_PodObject(¶ms[i]), NULL) < 0) + return -EINVAL; + + if (spa_pod_parser_get(&prs[0], SPA_POD_PodStruct(&ipod), NULL) < 0) + return -EINVAL; + if (ipod) { + infop = &info; + spa_pod_parser_pod(&prs[1], ipod); + demarshal_pw_endpoint_link_info(&prs[1], &f[1], infop); + } + + return pw_resource_notify(resource, struct pw_client_session_methods, + link_update, 0, link_id, change_mask, n_params, params, infop); +} + +static const struct pw_client_session_events pw_protocol_native_client_session_event_marshal = { + PW_VERSION_CLIENT_SESSION_EVENTS, + .set_param = client_session_marshal_set_param, + .link_set_param = client_session_marshal_link_set_param, + .link_request_state = client_session_marshal_link_request_state, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_client_session_event_demarshal[PW_CLIENT_SESSION_EVENT_NUM] = +{ + [PW_CLIENT_SESSION_EVENT_SET_PARAM] = { client_session_demarshal_set_param, 0 }, + [PW_CLIENT_SESSION_EVENT_LINK_SET_PARAM] = { client_session_demarshal_link_set_param, 0 }, + [PW_CLIENT_SESSION_EVENT_LINK_REQUEST_STATE] = { client_session_demarshal_link_request_state, 0 }, +}; + +static const struct pw_client_session_methods pw_protocol_native_client_session_method_marshal = { + PW_VERSION_CLIENT_SESSION_METHODS, + .add_listener = client_session_marshal_add_listener, + .update = client_session_marshal_update, + .link_update = client_session_marshal_link_update, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_client_session_method_demarshal[PW_CLIENT_SESSION_METHOD_NUM] = +{ + [PW_CLIENT_SESSION_METHOD_ADD_LISTENER] = { NULL, 0 }, + [PW_CLIENT_SESSION_METHOD_UPDATE] = { client_session_demarshal_update, 0 }, + [PW_CLIENT_SESSION_METHOD_LINK_UPDATE] = { client_session_demarshal_link_update, 0 }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_client_session_marshal = { + PW_TYPE_INTERFACE_ClientSession, + PW_VERSION_CLIENT_SESSION, + 0, + PW_CLIENT_SESSION_METHOD_NUM, + PW_CLIENT_SESSION_EVENT_NUM, + &pw_protocol_native_client_session_method_marshal, + &pw_protocol_native_client_session_method_demarshal, + &pw_protocol_native_client_session_event_marshal, + &pw_protocol_native_client_session_event_demarshal, +}; + +/*********************************************** + * ENDPOINT LINK + ***********************************************/ + +static void endpoint_link_proxy_marshal_info (void *data, + const struct pw_endpoint_link_info *info) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_EVENT_INFO, NULL); + + marshal_pw_endpoint_link_info(b, info); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void endpoint_link_resource_marshal_info (void *data, + const struct pw_endpoint_link_info *info) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_LINK_EVENT_INFO, NULL); + + marshal_pw_endpoint_link_info(b, info); + + pw_protocol_native_end_resource(resource, b); +} + +static void endpoint_link_proxy_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_proxy(proxy, b); +} +static void endpoint_link_resource_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_LINK_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_link_proxy_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_link_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int endpoint_link_resource_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_link_events *events, + void *data) +{ + struct pw_resource *resource = object; + pw_resource_add_object_listener(resource, listener, events, data); + return 0; +} + +static int endpoint_link_proxy_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_link_resource_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_LINK_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_link_proxy_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_link_resource_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_LINK_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_link_proxy_marshal_set_param(void *object, + uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_link_resource_marshal_set_param(void *object, + 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_ENDPOINT_LINK_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_link_proxy_marshal_request_state(void *object, + enum pw_endpoint_link_state state) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_LINK_METHOD_REQUEST_STATE, NULL); + + spa_pod_builder_add_struct(b, SPA_POD_Int(state)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_link_resource_marshal_request_state(void *object, + enum pw_endpoint_link_state state) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_LINK_METHOD_REQUEST_STATE, NULL); + + spa_pod_builder_add_struct(b, SPA_POD_Int(state)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_link_proxy_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_link_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_link_info(&prs, &f, &info); + + return pw_proxy_notify(proxy, struct pw_endpoint_link_events, + info, 0, &info); +} + +static int endpoint_link_resource_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_link_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_link_info(&prs, &f, &info); + + return pw_resource_notify(resource, struct pw_endpoint_link_events, + info, 0, &info); +} + +static int endpoint_link_proxy_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_link_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_link_resource_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_link_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_link_proxy_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_link_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_link_resource_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_link_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_link_proxy_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_link_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_link_resource_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_link_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_link_proxy_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_link_methods, + set_param, 0, id, flags, param); +} + +static int endpoint_link_resource_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_link_methods, + set_param, 0, id, flags, param); +} + +static int endpoint_link_proxy_demarshal_request_state(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + enum pw_endpoint_link_state state; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&state)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_link_methods, + request_state, 0, state); +} + +static int endpoint_link_resource_demarshal_request_state(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + enum pw_endpoint_link_state state; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&state)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_link_methods, + request_state, 0, state); +} + +static const struct pw_endpoint_link_events pw_protocol_native_endpoint_link_client_event_marshal = { + PW_VERSION_ENDPOINT_LINK_EVENTS, + .info = endpoint_link_proxy_marshal_info, + .param = endpoint_link_proxy_marshal_param, +}; + +static const struct pw_endpoint_link_events pw_protocol_native_endpoint_link_server_event_marshal = { + PW_VERSION_ENDPOINT_LINK_EVENTS, + .info = endpoint_link_resource_marshal_info, + .param = endpoint_link_resource_marshal_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_link_client_event_demarshal[PW_ENDPOINT_LINK_EVENT_NUM] = +{ + [PW_ENDPOINT_LINK_EVENT_INFO] = { endpoint_link_proxy_demarshal_info, 0 }, + [PW_ENDPOINT_LINK_EVENT_PARAM] = { endpoint_link_proxy_demarshal_param, 0 }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_link_server_event_demarshal[PW_ENDPOINT_LINK_EVENT_NUM] = +{ + [PW_ENDPOINT_LINK_EVENT_INFO] = { endpoint_link_resource_demarshal_info, 0 }, + [PW_ENDPOINT_LINK_EVENT_PARAM] = { endpoint_link_resource_demarshal_param, 0 }, +}; + +static const struct pw_endpoint_link_methods pw_protocol_native_endpoint_link_client_method_marshal = { + PW_VERSION_ENDPOINT_LINK_METHODS, + .add_listener = endpoint_link_proxy_marshal_add_listener, + .subscribe_params = endpoint_link_proxy_marshal_subscribe_params, + .enum_params = endpoint_link_proxy_marshal_enum_params, + .set_param = endpoint_link_proxy_marshal_set_param, + .request_state = endpoint_link_proxy_marshal_request_state, +}; + +static const struct pw_endpoint_link_methods pw_protocol_native_endpoint_link_server_method_marshal = { + PW_VERSION_ENDPOINT_LINK_METHODS, + .add_listener = endpoint_link_resource_marshal_add_listener, + .subscribe_params = endpoint_link_resource_marshal_subscribe_params, + .enum_params = endpoint_link_resource_marshal_enum_params, + .set_param = endpoint_link_resource_marshal_set_param, + .request_state = endpoint_link_resource_marshal_request_state, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_link_client_method_demarshal[PW_ENDPOINT_LINK_METHOD_NUM] = +{ + [PW_ENDPOINT_LINK_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_LINK_METHOD_SUBSCRIBE_PARAMS] = { endpoint_link_proxy_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_LINK_METHOD_ENUM_PARAMS] = { endpoint_link_proxy_demarshal_enum_params, 0 }, + [PW_ENDPOINT_LINK_METHOD_SET_PARAM] = { endpoint_link_proxy_demarshal_set_param, PW_PERM_W }, + [PW_ENDPOINT_LINK_METHOD_REQUEST_STATE] = { endpoint_link_proxy_demarshal_request_state, PW_PERM_W }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_link_server_method_demarshal[PW_ENDPOINT_LINK_METHOD_NUM] = +{ + [PW_ENDPOINT_LINK_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_LINK_METHOD_SUBSCRIBE_PARAMS] = { endpoint_link_resource_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_LINK_METHOD_ENUM_PARAMS] = { endpoint_link_resource_demarshal_enum_params, 0 }, + [PW_ENDPOINT_LINK_METHOD_SET_PARAM] = { endpoint_link_resource_demarshal_set_param, PW_PERM_W }, + [PW_ENDPOINT_LINK_METHOD_REQUEST_STATE] = { endpoint_link_resource_demarshal_request_state, PW_PERM_W }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_link_marshal = { + PW_TYPE_INTERFACE_EndpointLink, + PW_VERSION_ENDPOINT_LINK, + 0, + PW_ENDPOINT_LINK_METHOD_NUM, + PW_ENDPOINT_LINK_EVENT_NUM, + .client_marshal = &pw_protocol_native_endpoint_link_client_method_marshal, + .server_demarshal = pw_protocol_native_endpoint_link_server_method_demarshal, + .server_marshal = &pw_protocol_native_endpoint_link_server_event_marshal, + .client_demarshal = pw_protocol_native_endpoint_link_client_event_demarshal, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_link_impl_marshal = { + PW_TYPE_INTERFACE_EndpointLink, + PW_VERSION_ENDPOINT_LINK, + PW_PROTOCOL_MARSHAL_FLAG_IMPL, + PW_ENDPOINT_LINK_EVENT_NUM, + PW_ENDPOINT_LINK_METHOD_NUM, + .client_marshal = &pw_protocol_native_endpoint_link_client_event_marshal, + .server_demarshal = pw_protocol_native_endpoint_link_server_event_demarshal, + .server_marshal = &pw_protocol_native_endpoint_link_server_method_marshal, + .client_demarshal = pw_protocol_native_endpoint_link_client_method_demarshal, +}; + +/*********************************************** + * ENDPOINT STREAM + ***********************************************/ + +static void endpoint_stream_proxy_marshal_info (void *data, + const struct pw_endpoint_stream_info *info) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_STREAM_EVENT_INFO, NULL); + + marshal_pw_endpoint_stream_info(b, info); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void endpoint_stream_resource_marshal_info (void *data, + const struct pw_endpoint_stream_info *info) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_STREAM_EVENT_INFO, NULL); + + marshal_pw_endpoint_stream_info(b, info); + + pw_protocol_native_end_resource(resource, b); +} + +static void endpoint_stream_proxy_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_STREAM_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void endpoint_stream_resource_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_STREAM_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_stream_proxy_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_stream_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int endpoint_stream_resource_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_stream_events *events, + void *data) +{ + struct pw_resource *resource = object; + pw_resource_add_object_listener(resource, listener, events, data); + return 0; +} + +static int endpoint_stream_proxy_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_STREAM_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_stream_resource_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_STREAM_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_stream_proxy_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_STREAM_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_stream_resource_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_STREAM_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_stream_proxy_marshal_set_param(void *object, + uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_STREAM_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_stream_resource_marshal_set_param(void *object, + 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_ENDPOINT_STREAM_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_stream_proxy_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_stream_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_stream_info(&prs, &f, &info); + + return pw_proxy_notify(proxy, struct pw_endpoint_stream_events, + info, 0, &info); +} + +static int endpoint_stream_resource_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_stream_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_stream_info(&prs, &f, &info); + + return pw_resource_notify(resource, struct pw_endpoint_stream_events, + info, 0, &info); +} + +static int endpoint_stream_proxy_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_stream_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_stream_resource_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_stream_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_stream_proxy_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_stream_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_stream_resource_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_stream_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_stream_proxy_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_stream_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_stream_resource_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_stream_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_stream_proxy_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_stream_methods, + set_param, 0, id, flags, param); +} + +static int endpoint_stream_resource_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_stream_methods, + set_param, 0, id, flags, param); +} + +static const struct pw_endpoint_stream_events pw_protocol_native_endpoint_stream_client_event_marshal = { + PW_VERSION_ENDPOINT_STREAM_EVENTS, + .info = endpoint_stream_proxy_marshal_info, + .param = endpoint_stream_proxy_marshal_param, +}; + +static const struct pw_endpoint_stream_events pw_protocol_native_endpoint_stream_server_event_marshal = { + PW_VERSION_ENDPOINT_STREAM_EVENTS, + .info = endpoint_stream_resource_marshal_info, + .param = endpoint_stream_resource_marshal_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_stream_client_event_demarshal[PW_ENDPOINT_STREAM_EVENT_NUM] = +{ + [PW_ENDPOINT_STREAM_EVENT_INFO] = { endpoint_stream_proxy_demarshal_info, 0 }, + [PW_ENDPOINT_STREAM_EVENT_PARAM] = { endpoint_stream_proxy_demarshal_param, 0 }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_stream_server_event_demarshal[PW_ENDPOINT_STREAM_EVENT_NUM] = +{ + [PW_ENDPOINT_STREAM_EVENT_INFO] = { endpoint_stream_resource_demarshal_info, 0 }, + [PW_ENDPOINT_STREAM_EVENT_PARAM] = { endpoint_stream_resource_demarshal_param, 0 }, +}; + +static const struct pw_endpoint_stream_methods pw_protocol_native_endpoint_stream_client_method_marshal = { + PW_VERSION_ENDPOINT_STREAM_METHODS, + .add_listener = endpoint_stream_proxy_marshal_add_listener, + .subscribe_params = endpoint_stream_proxy_marshal_subscribe_params, + .enum_params = endpoint_stream_proxy_marshal_enum_params, + .set_param = endpoint_stream_proxy_marshal_set_param, +}; + +static const struct pw_endpoint_stream_methods pw_protocol_native_endpoint_stream_server_method_marshal = { + PW_VERSION_ENDPOINT_STREAM_METHODS, + .add_listener = endpoint_stream_resource_marshal_add_listener, + .subscribe_params = endpoint_stream_resource_marshal_subscribe_params, + .enum_params = endpoint_stream_resource_marshal_enum_params, + .set_param = endpoint_stream_resource_marshal_set_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_stream_client_method_demarshal[PW_ENDPOINT_STREAM_METHOD_NUM] = +{ + [PW_ENDPOINT_STREAM_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_STREAM_METHOD_SUBSCRIBE_PARAMS] = { endpoint_stream_proxy_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_STREAM_METHOD_ENUM_PARAMS] = { endpoint_stream_proxy_demarshal_enum_params, 0 }, + [PW_ENDPOINT_STREAM_METHOD_SET_PARAM] = { endpoint_stream_proxy_demarshal_set_param, PW_PERM_W }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_stream_server_method_demarshal[PW_ENDPOINT_STREAM_METHOD_NUM] = +{ + [PW_ENDPOINT_STREAM_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_STREAM_METHOD_SUBSCRIBE_PARAMS] = { endpoint_stream_resource_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_STREAM_METHOD_ENUM_PARAMS] = { endpoint_stream_resource_demarshal_enum_params, 0 }, + [PW_ENDPOINT_STREAM_METHOD_SET_PARAM] = { endpoint_stream_resource_demarshal_set_param, PW_PERM_W }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_stream_marshal = { + PW_TYPE_INTERFACE_EndpointStream, + PW_VERSION_ENDPOINT_STREAM, + 0, + PW_ENDPOINT_STREAM_METHOD_NUM, + PW_ENDPOINT_STREAM_EVENT_NUM, + .client_marshal = &pw_protocol_native_endpoint_stream_client_method_marshal, + .server_demarshal = pw_protocol_native_endpoint_stream_server_method_demarshal, + .server_marshal = &pw_protocol_native_endpoint_stream_server_event_marshal, + .client_demarshal = pw_protocol_native_endpoint_stream_client_event_demarshal, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_stream_impl_marshal = { + PW_TYPE_INTERFACE_EndpointStream, + PW_VERSION_ENDPOINT_STREAM, + PW_PROTOCOL_MARSHAL_FLAG_IMPL, + PW_ENDPOINT_STREAM_EVENT_NUM, + PW_ENDPOINT_STREAM_METHOD_NUM, + .client_marshal = &pw_protocol_native_endpoint_stream_client_event_marshal, + .server_demarshal = pw_protocol_native_endpoint_stream_server_event_demarshal, + .server_marshal = &pw_protocol_native_endpoint_stream_server_method_marshal, + .client_demarshal = pw_protocol_native_endpoint_stream_client_method_demarshal, +}; + +/*********************************************** + * ENDPOINT + ***********************************************/ + +static void endpoint_proxy_marshal_info (void *data, + const struct pw_endpoint_info *info) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_EVENT_INFO, NULL); + + marshal_pw_endpoint_info(b, info); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void endpoint_resource_marshal_info (void *data, + const struct pw_endpoint_info *info) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_EVENT_INFO, NULL); + + marshal_pw_endpoint_info(b, info); + + pw_protocol_native_end_resource(resource, b); +} + +static void endpoint_proxy_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void endpoint_resource_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_proxy_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int endpoint_resource_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_endpoint_events *events, + void *data) +{ + struct pw_resource *resource = object; + pw_resource_add_object_listener(resource, listener, events, data); + return 0; +} + +static int endpoint_proxy_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_resource_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_proxy_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_resource_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_proxy_marshal_set_param(void *object, + uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_resource_marshal_set_param(void *object, + 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_ENDPOINT_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_proxy_marshal_create_link(void *object, + const struct spa_dict *props) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_ENDPOINT_METHOD_CREATE_LINK, NULL); + + push_dict(b, props); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int endpoint_resource_marshal_create_link(void *object, + const struct spa_dict *props) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_ENDPOINT_METHOD_CREATE_LINK, NULL); + + push_dict(b, props); + + return pw_protocol_native_end_resource(resource, b); +} + +static int endpoint_proxy_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_info(&prs, &f, &info); + + return pw_proxy_notify(proxy, struct pw_endpoint_events, + info, 0, &info); +} + +static int endpoint_resource_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_endpoint_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_endpoint_info(&prs, &f, &info); + + return pw_resource_notify(resource, struct pw_endpoint_events, + info, 0, &info); +} + +static int endpoint_proxy_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_resource_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_events, + param, 0, seq, id, index, next, param); +} + +static int endpoint_proxy_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_resource_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_methods, + subscribe_params, 0, ids, n_ids); +} + +static int endpoint_proxy_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_resource_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int endpoint_proxy_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_endpoint_methods, + set_param, 0, id, flags, param); +} + +static int endpoint_resource_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_endpoint_methods, + set_param, 0, id, flags, param); +} + +static int endpoint_proxy_demarshal_create_link(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + + spa_pod_parser_init(&prs, msg->data, msg->size); + + parse_dict(&prs, &f, &props); + + return pw_proxy_notify(proxy, struct pw_endpoint_methods, + create_link, 0, &props); +} + +static int endpoint_resource_demarshal_create_link(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + + spa_pod_parser_init(&prs, msg->data, msg->size); + + parse_dict(&prs, &f, &props); + + return pw_resource_notify(resource, struct pw_endpoint_methods, + create_link, 0, &props); +} + +static const struct pw_endpoint_events pw_protocol_native_endpoint_client_event_marshal = { + PW_VERSION_ENDPOINT_EVENTS, + .info = endpoint_proxy_marshal_info, + .param = endpoint_proxy_marshal_param, +}; + +static const struct pw_endpoint_events pw_protocol_native_endpoint_server_event_marshal = { + PW_VERSION_ENDPOINT_EVENTS, + .info = endpoint_resource_marshal_info, + .param = endpoint_resource_marshal_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_client_event_demarshal[PW_ENDPOINT_EVENT_NUM] = +{ + [PW_ENDPOINT_EVENT_INFO] = { endpoint_proxy_demarshal_info, 0 }, + [PW_ENDPOINT_EVENT_PARAM] = { endpoint_proxy_demarshal_param, 0 }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_server_event_demarshal[PW_ENDPOINT_EVENT_NUM] = +{ + [PW_ENDPOINT_EVENT_INFO] = { endpoint_resource_demarshal_info, 0 }, + [PW_ENDPOINT_EVENT_PARAM] = { endpoint_resource_demarshal_param, 0 }, +}; + +static const struct pw_endpoint_methods pw_protocol_native_endpoint_client_method_marshal = { + PW_VERSION_ENDPOINT_METHODS, + .add_listener = endpoint_proxy_marshal_add_listener, + .subscribe_params = endpoint_proxy_marshal_subscribe_params, + .enum_params = endpoint_proxy_marshal_enum_params, + .set_param = endpoint_proxy_marshal_set_param, + .create_link = endpoint_proxy_marshal_create_link, +}; + +static const struct pw_endpoint_methods pw_protocol_native_endpoint_server_method_marshal = { + PW_VERSION_ENDPOINT_METHODS, + .add_listener = endpoint_resource_marshal_add_listener, + .subscribe_params = endpoint_resource_marshal_subscribe_params, + .enum_params = endpoint_resource_marshal_enum_params, + .set_param = endpoint_resource_marshal_set_param, + .create_link = endpoint_resource_marshal_create_link, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_client_method_demarshal[PW_ENDPOINT_METHOD_NUM] = +{ + [PW_ENDPOINT_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_METHOD_SUBSCRIBE_PARAMS] = { endpoint_proxy_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_METHOD_ENUM_PARAMS] = { endpoint_proxy_demarshal_enum_params, 0 }, + [PW_ENDPOINT_METHOD_SET_PARAM] = { endpoint_proxy_demarshal_set_param, PW_PERM_W }, + [PW_ENDPOINT_METHOD_CREATE_LINK] = { endpoint_proxy_demarshal_create_link, PW_PERM_X }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_endpoint_server_method_demarshal[PW_ENDPOINT_METHOD_NUM] = +{ + [PW_ENDPOINT_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_ENDPOINT_METHOD_SUBSCRIBE_PARAMS] = { endpoint_resource_demarshal_subscribe_params, 0 }, + [PW_ENDPOINT_METHOD_ENUM_PARAMS] = { endpoint_resource_demarshal_enum_params, 0 }, + [PW_ENDPOINT_METHOD_SET_PARAM] = { endpoint_resource_demarshal_set_param, PW_PERM_W }, + [PW_ENDPOINT_METHOD_CREATE_LINK] = { endpoint_resource_demarshal_create_link, PW_PERM_X }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_marshal = { + PW_TYPE_INTERFACE_Endpoint, + PW_VERSION_ENDPOINT, + 0, + PW_ENDPOINT_METHOD_NUM, + PW_ENDPOINT_EVENT_NUM, + .client_marshal = &pw_protocol_native_endpoint_client_method_marshal, + .server_demarshal = pw_protocol_native_endpoint_server_method_demarshal, + .server_marshal = &pw_protocol_native_endpoint_server_event_marshal, + .client_demarshal = pw_protocol_native_endpoint_client_event_demarshal, +}; + +static const struct pw_protocol_marshal pw_protocol_native_endpoint_impl_marshal = { + PW_TYPE_INTERFACE_Endpoint, + PW_VERSION_ENDPOINT, + PW_PROTOCOL_MARSHAL_FLAG_IMPL, + PW_ENDPOINT_EVENT_NUM, + PW_ENDPOINT_METHOD_NUM, + .client_marshal = &pw_protocol_native_endpoint_client_event_marshal, + .server_demarshal = pw_protocol_native_endpoint_server_event_demarshal, + .server_marshal = &pw_protocol_native_endpoint_server_method_marshal, + .client_demarshal = pw_protocol_native_endpoint_client_method_demarshal, +}; + +/*********************************************** + * SESSION + ***********************************************/ + +static void session_proxy_marshal_info (void *data, + const struct pw_session_info *info) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_SESSION_EVENT_INFO, NULL); + + marshal_pw_session_info(b, info); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void session_resource_marshal_info (void *data, + const struct pw_session_info *info) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_SESSION_EVENT_INFO, NULL); + + marshal_pw_session_info(b, info); + + pw_protocol_native_end_resource(resource, b); +} + +static void session_proxy_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_SESSION_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_proxy(proxy, b); +} + +static void session_resource_marshal_param (void *data, int seq, uint32_t id, + uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct pw_resource *resource = data; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_SESSION_EVENT_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(seq), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(next), + SPA_POD_Pod(param)); + + pw_protocol_native_end_resource(resource, b); +} + +static int session_proxy_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_session_events *events, + void *data) +{ + struct pw_proxy *proxy = object; + pw_proxy_add_object_listener(proxy, listener, events, data); + return 0; +} + +static int session_resource_marshal_add_listener(void *object, + struct spa_hook *listener, + const struct pw_session_events *events, + void *data) +{ + struct pw_resource *resource = object; + pw_resource_add_object_listener(resource, listener, events, data); + return 0; +} + +static int session_proxy_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_SESSION_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int session_resource_marshal_subscribe_params(void *object, + uint32_t *ids, uint32_t n_ids) +{ + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_SESSION_METHOD_SUBSCRIBE_PARAMS, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, n_ids, ids)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int session_proxy_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_SESSION_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int session_resource_marshal_enum_params(void *object, + int seq, uint32_t id, + uint32_t index, uint32_t num, + const struct spa_pod *filter) +{ + struct pw_protocol_native_message *msg; + struct pw_resource *resource = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_resource(resource, + PW_SESSION_METHOD_ENUM_PARAMS, &msg); + + spa_pod_builder_add_struct(b, + SPA_POD_Int(SPA_RESULT_RETURN_ASYNC(msg->seq)), + SPA_POD_Id(id), + SPA_POD_Int(index), + SPA_POD_Int(num), + SPA_POD_Pod(filter)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int session_proxy_marshal_set_param(void *object, + uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct pw_proxy *proxy = object; + struct spa_pod_builder *b; + + b = pw_protocol_native_begin_proxy(proxy, + PW_SESSION_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_proxy(proxy, b); +} + +static int session_resource_marshal_set_param(void *object, + 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_SESSION_METHOD_SET_PARAM, NULL); + + spa_pod_builder_add_struct(b, + SPA_POD_Id(id), + SPA_POD_Int(flags), + SPA_POD_Pod(param)); + + return pw_protocol_native_end_resource(resource, b); +} + +static int session_proxy_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_session_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_session_info(&prs, &f, &info); + + return pw_proxy_notify(proxy, struct pw_session_events, + info, 0, &info); +} + +static int session_resource_demarshal_info(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + struct spa_pod_frame f; + struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_session_info info = { .props = &props }; + + spa_pod_parser_init(&prs, msg->data, msg->size); + + demarshal_pw_session_info(&prs, &f, &info); + + return pw_resource_notify(resource, struct pw_session_events, + info, 0, &info); +} + +static int session_proxy_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_session_events, + param, 0, seq, id, index, next, param); +} + +static int session_resource_demarshal_param(void *data, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = data; + struct spa_pod_parser prs; + uint32_t id, index, next; + int seq; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&next), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_session_events, + param, 0, seq, id, index, next, param); +} + +static int session_proxy_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_session_methods, + subscribe_params, 0, ids, n_ids); +} + +static int session_resource_demarshal_subscribe_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t csize, ctype, n_ids; + uint32_t *ids; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Array(&csize, &ctype, &n_ids, &ids)) < 0) + return -EINVAL; + + if (ctype != SPA_TYPE_Id) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_session_methods, + subscribe_params, 0, ids, n_ids); +} + +static int session_proxy_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_session_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int session_resource_demarshal_enum_params(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, index, num; + int seq; + struct spa_pod *filter; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Int(&seq), + SPA_POD_Id(&id), + SPA_POD_Int(&index), + SPA_POD_Int(&num), + SPA_POD_Pod(&filter)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_session_methods, + enum_params, 0, seq, id, index, num, filter); +} + +static int session_proxy_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_proxy *proxy = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_proxy_notify(proxy, struct pw_session_methods, + set_param, 0, id, flags, param); +} + +static int session_resource_demarshal_set_param(void *object, + const struct pw_protocol_native_message *msg) +{ + struct pw_resource *resource = object; + struct spa_pod_parser prs; + uint32_t id, flags; + struct spa_pod *param; + + spa_pod_parser_init(&prs, msg->data, msg->size); + if (spa_pod_parser_get_struct(&prs, + SPA_POD_Id(&id), + SPA_POD_Int(&flags), + SPA_POD_Pod(¶m)) < 0) + return -EINVAL; + + return pw_resource_notify(resource, struct pw_session_methods, + set_param, 0, id, flags, param); +} + +static const struct pw_session_events pw_protocol_native_session_client_event_marshal = { + PW_VERSION_SESSION_EVENTS, + .info = session_proxy_marshal_info, + .param = session_proxy_marshal_param, +}; + +static const struct pw_session_events pw_protocol_native_session_server_event_marshal = { + PW_VERSION_SESSION_EVENTS, + .info = session_resource_marshal_info, + .param = session_resource_marshal_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_session_client_event_demarshal[PW_SESSION_EVENT_NUM] = +{ + [PW_SESSION_EVENT_INFO] = { session_proxy_demarshal_info, 0 }, + [PW_SESSION_EVENT_PARAM] = { session_proxy_demarshal_param, 0 }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_session_server_event_demarshal[PW_SESSION_EVENT_NUM] = +{ + [PW_SESSION_EVENT_INFO] = { session_resource_demarshal_info, 0 }, + [PW_SESSION_EVENT_PARAM] = { session_resource_demarshal_param, 0 }, +}; + +static const struct pw_session_methods pw_protocol_native_session_client_method_marshal = { + PW_VERSION_SESSION_METHODS, + .add_listener = session_proxy_marshal_add_listener, + .subscribe_params = session_proxy_marshal_subscribe_params, + .enum_params = session_proxy_marshal_enum_params, + .set_param = session_proxy_marshal_set_param, +}; + +static const struct pw_session_methods pw_protocol_native_session_server_method_marshal = { + PW_VERSION_SESSION_METHODS, + .add_listener = session_resource_marshal_add_listener, + .subscribe_params = session_resource_marshal_subscribe_params, + .enum_params = session_resource_marshal_enum_params, + .set_param = session_resource_marshal_set_param, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_session_client_method_demarshal[PW_SESSION_METHOD_NUM] = +{ + [PW_SESSION_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_SESSION_METHOD_SUBSCRIBE_PARAMS] = { session_proxy_demarshal_subscribe_params, 0 }, + [PW_SESSION_METHOD_ENUM_PARAMS] = { session_proxy_demarshal_enum_params, 0 }, + [PW_SESSION_METHOD_SET_PARAM] = { session_proxy_demarshal_set_param, PW_PERM_W }, +}; + +static const struct pw_protocol_native_demarshal +pw_protocol_native_session_server_method_demarshal[PW_SESSION_METHOD_NUM] = +{ + [PW_SESSION_METHOD_ADD_LISTENER] = { demarshal_add_listener_enotsup, 0 }, + [PW_SESSION_METHOD_SUBSCRIBE_PARAMS] = { session_resource_demarshal_subscribe_params, 0 }, + [PW_SESSION_METHOD_ENUM_PARAMS] = { session_resource_demarshal_enum_params, 0 }, + [PW_SESSION_METHOD_SET_PARAM] = { session_resource_demarshal_set_param, PW_PERM_W }, +}; + +static const struct pw_protocol_marshal pw_protocol_native_session_marshal = { + PW_TYPE_INTERFACE_Session, + PW_VERSION_SESSION, + 0, + PW_SESSION_METHOD_NUM, + PW_SESSION_EVENT_NUM, + .client_marshal = &pw_protocol_native_session_client_method_marshal, + .server_demarshal = pw_protocol_native_session_server_method_demarshal, + .server_marshal = &pw_protocol_native_session_server_event_marshal, + .client_demarshal = pw_protocol_native_session_client_event_demarshal, +}; + +static const struct pw_protocol_marshal pw_protocol_native_session_impl_marshal = { + PW_TYPE_INTERFACE_Session, + PW_VERSION_SESSION, + PW_PROTOCOL_MARSHAL_FLAG_IMPL, + PW_SESSION_EVENT_NUM, + PW_SESSION_METHOD_NUM, + .client_marshal = &pw_protocol_native_session_client_event_marshal, + .server_demarshal = pw_protocol_native_session_server_event_demarshal, + .server_marshal = &pw_protocol_native_session_server_method_marshal, + .client_demarshal = pw_protocol_native_session_client_method_demarshal, +}; + +int pw_protocol_native_ext_session_manager_init(struct pw_context *context) +{ + struct pw_protocol *protocol; + + protocol = pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native); + if (protocol == NULL) + return -EPROTO; + + /* deprecated */ + pw_protocol_add_marshal(protocol, &pw_protocol_native_client_endpoint_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_client_session_marshal); + + /* client <-> server */ + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_link_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_stream_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_session_marshal); + + /* impl <-> server */ + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_link_impl_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_stream_impl_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_endpoint_impl_marshal); + pw_protocol_add_marshal(protocol, &pw_protocol_native_session_impl_marshal); + + return 0; +} |