From 849e0599b67bad19ae24ce520901acb96b5c9f38 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 21 Jun 2017 12:11:54 +0200 Subject: [PATCH] Make extensions Make the protocol-native and client-node extensions --- Makefile | 1 + pipewire/client/context.c | 12 +- pipewire/client/context.h | 1 + pipewire/client/extension.c | 140 +++ pipewire/client/extension.h | 72 ++ pipewire/client/interfaces.h | 257 ----- pipewire/client/meson.build | 4 +- pipewire/client/protocol-native.h | 22 - pipewire/client/protocol.c | 9 + pipewire/client/stream.c | 1 + pipewire/extensions/client-node.h | 297 ++++++ pipewire/modules/extension-client-node.c | 66 ++ pipewire/modules/extension-protocol-native.c | 66 ++ pipewire/modules/meson.build | 10 +- pipewire/modules/module-client-node.c | 4 + .../modules/module-client-node/client-node.h | 4 +- .../module-client-node}/protocol-native.c | 891 ++++++++-------- pipewire/modules/module-protocol-native.c | 7 +- .../module-protocol-native}/protocol-native.c | 968 ++++++++++-------- pipewire/server/meson.build | 2 - pipewire/server/protocol-native.h | 22 - 21 files changed, 1625 insertions(+), 1231 deletions(-) create mode 100644 pipewire/client/extension.c create mode 100644 pipewire/client/extension.h delete mode 100644 pipewire/client/protocol-native.h create mode 100644 pipewire/extensions/client-node.h create mode 100644 pipewire/modules/extension-client-node.c create mode 100644 pipewire/modules/extension-protocol-native.c rename pipewire/{server => modules/module-client-node}/protocol-native.c (51%) rename pipewire/{client => modules/module-protocol-native}/protocol-native.c (55%) delete mode 100644 pipewire/server/protocol-native.h diff --git a/Makefile b/Makefile index d65f9a409..09f22432e 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ run: monitor: SPA_PLUGIN_DIR=build/spa/plugins \ + PIPEWIRE_MODULE_DIR=build/pipewire/modules/ \ build/pipewire/tools/pipewire-monitor dist: diff --git a/pipewire/client/context.c b/pipewire/client/context.c index 509664f52..faab147d8 100644 --- a/pipewire/client/context.c +++ b/pipewire/client/context.c @@ -26,6 +26,7 @@ #include "pipewire/client/pipewire.h" #include "pipewire/client/context.h" +#include "pipewire/client/extension.h" #include "pipewire/client/introspect.h" #include "pipewire/client/interfaces.h" #include "pipewire/client/protocol-native.h" @@ -443,8 +444,6 @@ struct pw_context *pw_context_new(struct pw_loop *loop, this->loop = loop; - this->protocol = pw_protocol_native_client_init(); - pw_type_init(&this->type); spa_debug_set_type_map(this->type.map); @@ -462,6 +461,7 @@ struct pw_context *pw_context_new(struct pw_loop *loop, pw_map_init(&this->objects, 64, 32); pw_map_init(&this->types, 64, 32); + spa_list_init(&this->extension_list); spa_list_init(&this->stream_list); spa_list_init(&this->proxy_list); @@ -469,6 +469,11 @@ struct pw_context *pw_context_new(struct pw_loop *loop, pw_signal_init(&this->subscription); pw_signal_init(&this->destroy_signal); + pw_extension_load(this, "libpipewire-module-protocol-native", NULL); + pw_extension_load(this, "libpipewire-module-client-node", NULL); + + this->protocol = pw_protocol_get(PW_TYPE_PROTOCOL__Native); + return this; no_mem: @@ -482,6 +487,7 @@ void pw_context_destroy(struct pw_context *context) struct context *impl = SPA_CONTAINER_OF(context, struct context, this); struct pw_stream *stream, *t1; struct pw_proxy *proxy, *t2; + struct pw_extension *ext, *t3; pw_log_debug("context %p: destroy", context); pw_signal_emit(&context->destroy_signal, context); @@ -495,6 +501,8 @@ void pw_context_destroy(struct pw_context *context) pw_stream_destroy(stream); spa_list_for_each_safe(proxy, t2, &context->proxy_list, link) pw_proxy_destroy(proxy); + spa_list_for_each_safe(ext, t3, &context->extension_list, link) + pw_extension_destroy(ext); pw_map_clear(&context->objects); pw_map_clear(&context->types); diff --git a/pipewire/client/context.h b/pipewire/client/context.h index fe251f6d1..e73884f6a 100644 --- a/pipewire/client/context.h +++ b/pipewire/client/context.h @@ -157,6 +157,7 @@ struct pw_context { uint32_t n_types; /**< number of client types */ struct pw_map types; /**< client types */ + struct spa_list extension_list; /**< list of \ref pw_extension objects */ struct spa_list stream_list; /**< list of \ref pw_stream objects */ struct spa_list proxy_list; /**< list of \ref pw_proxy objects */ diff --git a/pipewire/client/extension.c b/pipewire/client/extension.c new file mode 100644 index 000000000..1025b4a2b --- /dev/null +++ b/pipewire/client/extension.c @@ -0,0 +1,140 @@ +/* PipeWire + * Copyright (C) 2016 Axis Communications + * @author Linus Svensson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "pipewire/client/pipewire.h" +#include "pipewire/client/interfaces.h" +#include "pipewire/client/utils.h" +#include "pipewire/client/extension.h" + +/** \cond */ +struct impl { + struct pw_extension this; + void *hnd; +}; +/** \endcond */ + +/** Load an extension \memberof pw_extension + * + * \param context a \ref pw_context + * \param name name of the extension to load + * \param args A string with arguments for the extension + * \param[out] err Return location for an error string, or NULL + * \return A \ref pw_extension if the extension could be loaded, or NULL on failure. + */ +struct pw_extension *pw_extension_load(struct pw_context *context, + const char *name, const char *args) +{ + struct pw_extension *this; + struct impl *impl; + void *hnd; + char *filename = NULL; + const char *module_dir; + pw_extension_init_func_t init_func; + + module_dir = getenv("PIPEWIRE_MODULE_DIR"); + if (module_dir == NULL) + module_dir = MODULEDIR; + + pw_log_debug("PIPEWIRE_MODULE_DIR set to: %s", module_dir); + + asprintf(&filename, "%s/%s.so", module_dir, name); + if (filename == NULL) + goto no_filename; + + pw_log_debug("trying to load extension: %s (%s)", name, filename); + + hnd = dlopen(filename, RTLD_NOW | RTLD_LOCAL); + + if (hnd == NULL) + goto open_failed; + + if ((init_func = dlsym(hnd, PIPEWIRE_SYMBOL_EXTENSION_INIT)) == NULL) + goto no_pw_extension; + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + goto no_mem; + + impl->hnd = hnd; + + this = &impl->this; + this->context = context; + this->filename = filename; + this->args = args ? strdup(args) : NULL; + this->props = NULL; + + pw_signal_init(&this->destroy_signal); + + if (!init_func(this, (char *) args)) + goto init_failed; + + spa_list_insert(&context->extension_list, &this->link); + + pw_log_debug("loaded extension: %s", filename); + + return this; + + no_filename: + pw_log_error("No memory"); + return NULL; + open_failed: + pw_log_error("Failed to open module: \"%s\" %s", filename, dlerror()); + free(filename); + return NULL; + no_mem: + no_pw_extension: + pw_log_error("\"%s\" is not a pipewire extension", name); + dlclose(hnd); + free(filename); + return NULL; + init_failed: + pw_log_error("\"%s\" failed to initialize", name); + pw_extension_destroy(this); + return NULL; +} + +/** Destroy a extension + * \param extension the extension to destroy + * \memberof pw_extension + */ +void pw_extension_destroy(struct pw_extension *extension) +{ + struct impl *impl = SPA_CONTAINER_OF(extension, struct impl, this); + + pw_signal_emit(&extension->destroy_signal, extension); + + if (extension->filename) + free((char *) extension->filename); + if (extension->args) + free((char *) extension->args); + if (extension->props) + pw_properties_free(extension->props); + dlclose(impl->hnd); + free(impl); +} diff --git a/pipewire/client/extension.h b/pipewire/client/extension.h new file mode 100644 index 000000000..c6c2f9b67 --- /dev/null +++ b/pipewire/client/extension.h @@ -0,0 +1,72 @@ +/* PipeWire + * Copyright (C) 2016 Axis Communications + * @author Linus Svensson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PIPEWIRE_EXTENSION_H__ +#define __PIPEWIRE_EXTENSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define PIPEWIRE_SYMBOL_EXTENSION_INIT "pipewire__extension_init" + +/** \class pw_extension + * + * A dynamically loadable extension + */ +struct pw_extension { + struct pw_context *context; /**< the client context */ + struct spa_list link; /**< link in the context extension_list */ + + const char *filename; /**< filename of extension */ + const char *args; /**< argument for the extension */ + struct pw_properties *props; /**< extra properties */ + + void *user_data; /**< extension user_data */ + + /** Emited when the extension is destroyed */ + PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_extension *extension)); +}; + +/** Module init function signature \memberof pw_extension + * + * \param extension A \ref pw_extension + * \param args Arguments to the extension + * \return true on success, false otherwise + * + * A extension should provide an init function with this signature. This function + * will be called when a extension is loaded. + */ +typedef bool (*pw_extension_init_func_t) (struct pw_extension *extension, char *args); + +struct pw_extension * +pw_extension_load(struct pw_context *context, + const char *name, const char *args); + +void +pw_extension_destroy(struct pw_extension *extension); + +#ifdef __cplusplus +} +#endif + +#endif /* __PIPEWIRE_EXTENSION_H__ */ diff --git a/pipewire/client/interfaces.h b/pipewire/client/interfaces.h index 588d89c1e..14c6a119b 100644 --- a/pipewire/client/interfaces.h +++ b/pipewire/client/interfaces.h @@ -306,263 +306,6 @@ struct pw_node_events { #define pw_node_notify_info(r,...) ((struct pw_node_events*)r->iface->events)->info(r,__VA_ARGS__) -/** information about a buffer */ -struct pw_client_node_buffer { - uint32_t mem_id; /**< the memory id for the metadata */ - uint32_t offset; /**< offset in memory */ - uint32_t size; /**< size in memory */ - struct spa_buffer *buffer; /**< buffer describing metadata and buffer memory */ -}; - -#define PW_VERSION_CLIENT_NODE 0 - -#define PW_CLIENT_NODE_METHOD_DONE 0 -#define PW_CLIENT_NODE_METHOD_UPDATE 1 -#define PW_CLIENT_NODE_METHOD_PORT_UPDATE 2 -#define PW_CLIENT_NODE_METHOD_EVENT 3 -#define PW_CLIENT_NODE_METHOD_DESTROY 4 -#define PW_CLIENT_NODE_METHOD_NUM 5 - -/** \ref pw_client_node methods */ -struct pw_client_node_methods { - /** Complete an async operation */ - void (*done) (void *object, int seq, int res); - - /** - * Update the node ports and properties - * - * Update the maximum number of ports and the properties of the - * client node. - * \param change_mask bitfield with changed parameters - * \param max_input_ports new max input ports - * \param max_output_ports new max output ports - * \param props new properties - */ - void (*update) (void *object, -#define PW_CLIENT_NODE_UPDATE_MAX_INPUTS (1 << 0) -#define PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS (1 << 1) -#define PW_CLIENT_NODE_UPDATE_PROPS (1 << 2) - uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, - const struct spa_props *props); - - /** - * Update a node port - * - * Update the information of one port of a node. - * \param direction the direction of the port - * \param port_id the port id to update - * \param change_mask a bitfield of changed items - * \param n_possible_formats number of possible formats - * \param possible_formats array of possible formats on the port - * \param format the current format on the port - * \param n_params number of port parameters - * \param params array of port parameters - * \param info port information - */ - void (*port_update) (void *object, - enum spa_direction direction, - uint32_t port_id, -#define PW_CLIENT_NODE_PORT_UPDATE_POSSIBLE_FORMATS (1 << 0) -#define PW_CLIENT_NODE_PORT_UPDATE_FORMAT (1 << 1) -#define PW_CLIENT_NODE_PORT_UPDATE_PARAMS (1 << 2) -#define PW_CLIENT_NODE_PORT_UPDATE_INFO (1 << 3) - uint32_t change_mask, - uint32_t n_possible_formats, - const struct spa_format **possible_formats, - const struct spa_format *format, - uint32_t n_params, - const struct spa_param **params, - const struct spa_port_info *info); - /** - * Send an event to the node - * \param event the event to send - */ - void (*event) (void *object, struct spa_event *event); - /** - * Destroy the client_node - */ - void (*destroy) (void *object); -}; - -#define pw_client_node_do_done(r,...) ((struct pw_client_node_methods*)r->iface->methods)->done(r,__VA_ARGS__) -#define pw_client_node_do_update(r,...) ((struct pw_client_node_methods*)r->iface->methods)->update(r,__VA_ARGS__) -#define pw_client_node_do_port_update(r,...) ((struct pw_client_node_methods*)r->iface->methods)->port_update(r,__VA_ARGS__) -#define pw_client_node_do_event(r,...) ((struct pw_client_node_methods*)r->iface->methods)->event(r,__VA_ARGS__) -#define pw_client_node_do_destroy(r) ((struct pw_client_node_methods*)r->iface->methods)->destroy(r) - -#define PW_CLIENT_NODE_EVENT_SET_PROPS 0 -#define PW_CLIENT_NODE_EVENT_EVENT 1 -#define PW_CLIENT_NODE_EVENT_ADD_PORT 2 -#define PW_CLIENT_NODE_EVENT_REMOVE_PORT 3 -#define PW_CLIENT_NODE_EVENT_SET_FORMAT 4 -#define PW_CLIENT_NODE_EVENT_SET_PARAM 5 -#define PW_CLIENT_NODE_EVENT_ADD_MEM 6 -#define PW_CLIENT_NODE_EVENT_USE_BUFFERS 7 -#define PW_CLIENT_NODE_EVENT_NODE_COMMAND 8 -#define PW_CLIENT_NODE_EVENT_PORT_COMMAND 9 -#define PW_CLIENT_NODE_EVENT_TRANSPORT 10 -#define PW_CLIENT_NODE_EVENT_NUM 11 - -/** \ref pw_client_node events */ -struct pw_client_node_events { - /** - * Notify of a property change - * - * When the server configures the properties on the node - * this event is sent - * - * \param seq a sequence number - * \param props the props to set - */ - void (*set_props) (void *object, - uint32_t seq, - const struct spa_props *props); - /** - * Receive an event from the client node - * \param event the received event */ - void (*event) (void *object, const struct spa_event *event); - /** - * A new port was added to the node - * - * The server can at any time add a port to the node when there - * are free ports available. - * - * \param seq a sequence number - * \param direction the direction of the port - * \param port_id the new port id - */ - void (*add_port) (void *object, - uint32_t seq, - enum spa_direction direction, - uint32_t port_id); - /** - * A port was removed from the node - * - * \param seq a sequence number - * \param direction a port direction - * \param port_id the remove port id - */ - void (*remove_port) (void *object, - uint32_t seq, - enum spa_direction direction, - uint32_t port_id); - /** - * A format was configured on the port - * - * \param seq a sequence number - * \param direction a port direction - * \param port_id the port id - * \param flags flags used when setting the format - * \param format the new format - */ - void (*set_format) (void *object, - uint32_t seq, - enum spa_direction direction, - uint32_t port_id, - uint32_t flags, - const struct spa_format *format); - /** - * A parameter was configured on the port - * - * \param seq a sequence number - * \param direction a port direction - * \param port_id the port id - * \param param the new param - */ - void (*set_param) (void *object, - uint32_t seq, - enum spa_direction direction, - uint32_t port_id, - const struct spa_param *param); - /** - * Memory was added for a port - * - * \param direction a port direction - * \param port_id the port id - * \param mem_id the id of the memory - * \param type the memory type - * \param memfd the fd of the memory - * \param flags flags for the \a memfd - * \param offset valid offset of mapped memory from \a memfd - * \param size valid size of mapped memory from \a memfd - */ - void (*add_mem) (void *object, - enum spa_direction direction, - uint32_t port_id, - uint32_t mem_id, - uint32_t type, - int memfd, - uint32_t flags, - uint32_t offset, - uint32_t size); - /** - * Notify the port of buffers - * - * \param seq a sequence number - * \param direction a port direction - * \param port_id the port id - * \param n_buffer the number of buffers - * \param buffers and array of buffer descriptions - */ - void (*use_buffers) (void *object, - uint32_t seq, - enum spa_direction direction, - uint32_t port_id, - uint32_t n_buffers, - struct pw_client_node_buffer *buffers); - /** - * Notify of a new node command - * - * \param seq a sequence number - * \param command the command - */ - void (*node_command) (void *object, uint32_t seq, const struct spa_command *command); - /** - * Notify of a new port command - * - * \param direction a port direction - * \param port_id the port id - * \param command the command - */ - void (*port_command) (void *object, - enum spa_direction direction, - uint32_t port_id, - const struct spa_command *command); - - /** - * Notify of a new transport area - * - * The transport area is used to exchange real-time commands between - * the client and the server. - * - * \param readfd fd for signal data can be read - * \param writefd fd for signal data can be written - * \param memfd the memory fd of the area - * \param offset the offset to map - * \param size the size to map - */ - void (*transport) (void *object, - int readfd, - int writefd, - int memfd, - uint32_t offset, - uint32_t size); -}; - -#define pw_client_node_notify_set_props(r,...) ((struct pw_client_node_events*)r->iface->events)->props(r,__VA_ARGS__) -#define pw_client_node_notify_event(r,...) ((struct pw_client_node_events*)r->iface->events)->event(r,__VA_ARGS__) -#define pw_client_node_notify_add_port(r,...) ((struct pw_client_node_events*)r->iface->events)->add_port(r,__VA_ARGS__) -#define pw_client_node_notify_remove_port(r,...) ((struct pw_client_node_events*)r->iface->events)->remove_port(r,__VA_ARGS__) -#define pw_client_node_notify_set_format(r,...) ((struct pw_client_node_events*)r->iface->events)->set_format(r,__VA_ARGS__) -#define pw_client_node_notify_set_param(r,...) ((struct pw_client_node_events*)r->iface->events)->set_param(r,__VA_ARGS__) -#define pw_client_node_notify_add_mem(r,...) ((struct pw_client_node_events*)r->iface->events)->add_mem(r,__VA_ARGS__) -#define pw_client_node_notify_use_buffers(r,...) ((struct pw_client_node_events*)r->iface->events)->use_buffers(r,__VA_ARGS__) -#define pw_client_node_notify_node_command(r,...) ((struct pw_client_node_events*)r->iface->events)->node_command(r,__VA_ARGS__) -#define pw_client_node_notify_port_command(r,...) ((struct pw_client_node_events*)r->iface->events)->port_command(r,__VA_ARGS__) -#define pw_client_node_notify_transport(r,...) ((struct pw_client_node_events*)r->iface->events)->transport(r,__VA_ARGS__) - #define PW_VERSION_CLIENT 0 #define PW_CLIENT_EVENT_INFO 0 diff --git a/pipewire/client/meson.build b/pipewire/client/meson.build index 279eeaa2c..d062d2614 100644 --- a/pipewire/client/meson.build +++ b/pipewire/client/meson.build @@ -2,6 +2,7 @@ pipewire_headers = [ 'array.h', 'connection.h', 'context.h', + 'extension.h', 'interfaces.h', 'introspect.h', 'log.h', @@ -11,7 +12,6 @@ pipewire_headers = [ 'pipewire.h', 'properties.h', 'protocol.h', - 'protocol-native.h', 'proxy.h', 'rtkit.h', 'sig.h', @@ -26,6 +26,7 @@ pipewire_headers = [ pipewire_sources = [ 'connection.c', 'context.c', + 'extension.c', 'introspect.c', 'log.c', 'loop.c', @@ -33,7 +34,6 @@ pipewire_sources = [ 'pipewire.c', 'properties.c', 'protocol.c', - 'protocol-native.c', 'proxy.c', 'stream.c', 'rtkit.c', diff --git a/pipewire/client/protocol-native.h b/pipewire/client/protocol-native.h deleted file mode 100644 index f76f75d3d..000000000 --- a/pipewire/client/protocol-native.h +++ /dev/null @@ -1,22 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -struct pw_protocol *pw_protocol_native_client_init(void); diff --git a/pipewire/client/protocol.c b/pipewire/client/protocol.c index a09582986..7ebc7d02c 100644 --- a/pipewire/client/protocol.c +++ b/pipewire/client/protocol.c @@ -48,6 +48,8 @@ struct pw_protocol *pw_protocol_get(const char *name) spa_list_init(&protocol->iface_list); spa_list_insert(impl->protocol_list.prev, &protocol->link); + pw_log_info("Created protocol %s", name); + return protocol; } @@ -57,12 +59,19 @@ pw_protocol_add_interfaces(struct pw_protocol *protocol, const struct pw_interface *server_iface) { struct pw_protocol_iface *iface; + const char *type; + uint32_t version; iface = calloc(1, sizeof(struct pw_protocol_iface)); iface->client_iface = client_iface; iface->server_iface = server_iface; spa_list_insert(protocol->iface_list.prev, &iface->link); + + type = client_iface ? client_iface->type : server_iface->type; + version = client_iface ? client_iface->version : server_iface->version; + + pw_log_info("Add iface %s:%d to protocol %s", type, version, protocol->name); } const struct pw_interface * diff --git a/pipewire/client/stream.c b/pipewire/client/stream.c index 370708674..4920bd5d8 100644 --- a/pipewire/client/stream.c +++ b/pipewire/client/stream.c @@ -35,6 +35,7 @@ #include "pipewire/client/stream.h" #include "pipewire/client/transport.h" #include "pipewire/client/utils.h" +#include "pipewire/extensions/client-node.h" /** \cond */ diff --git a/pipewire/extensions/client-node.h b/pipewire/extensions/client-node.h new file mode 100644 index 000000000..0ddc803cc --- /dev/null +++ b/pipewire/extensions/client-node.h @@ -0,0 +1,297 @@ +/* PipeWire + * Copyright (C) 2016 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PIPEWIRE_EXT_CLIENT_NODE_H__ +#define __PIPEWIRE_EXT_CLIENT_NODE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +#define PIPEWIRE_TYPE__ClientNode PIPEWIRE_TYPE_NODE_BASE "Client" +#define PIPEWIRE_TYPE_CLIENT_NODE_BASE PIPEWIRE_TYPE__ClientNode ":" + +/** information about a buffer */ +struct pw_client_node_buffer { + uint32_t mem_id; /**< the memory id for the metadata */ + uint32_t offset; /**< offset in memory */ + uint32_t size; /**< size in memory */ + struct spa_buffer *buffer; /**< buffer describing metadata and buffer memory */ +}; + +#define PW_VERSION_CLIENT_NODE 0 + +#define PW_CLIENT_NODE_METHOD_DONE 0 +#define PW_CLIENT_NODE_METHOD_UPDATE 1 +#define PW_CLIENT_NODE_METHOD_PORT_UPDATE 2 +#define PW_CLIENT_NODE_METHOD_EVENT 3 +#define PW_CLIENT_NODE_METHOD_DESTROY 4 +#define PW_CLIENT_NODE_METHOD_NUM 5 + +/** \ref pw_client_node methods */ +struct pw_client_node_methods { + /** Complete an async operation */ + void (*done) (void *object, int seq, int res); + + /** + * Update the node ports and properties + * + * Update the maximum number of ports and the properties of the + * client node. + * \param change_mask bitfield with changed parameters + * \param max_input_ports new max input ports + * \param max_output_ports new max output ports + * \param props new properties + */ + void (*update) (void *object, +#define PW_CLIENT_NODE_UPDATE_MAX_INPUTS (1 << 0) +#define PW_CLIENT_NODE_UPDATE_MAX_OUTPUTS (1 << 1) +#define PW_CLIENT_NODE_UPDATE_PROPS (1 << 2) + uint32_t change_mask, + uint32_t max_input_ports, + uint32_t max_output_ports, + const struct spa_props *props); + + /** + * Update a node port + * + * Update the information of one port of a node. + * \param direction the direction of the port + * \param port_id the port id to update + * \param change_mask a bitfield of changed items + * \param n_possible_formats number of possible formats + * \param possible_formats array of possible formats on the port + * \param format the current format on the port + * \param n_params number of port parameters + * \param params array of port parameters + * \param info port information + */ + void (*port_update) (void *object, + enum spa_direction direction, + uint32_t port_id, +#define PW_CLIENT_NODE_PORT_UPDATE_POSSIBLE_FORMATS (1 << 0) +#define PW_CLIENT_NODE_PORT_UPDATE_FORMAT (1 << 1) +#define PW_CLIENT_NODE_PORT_UPDATE_PARAMS (1 << 2) +#define PW_CLIENT_NODE_PORT_UPDATE_INFO (1 << 3) + uint32_t change_mask, + uint32_t n_possible_formats, + const struct spa_format **possible_formats, + const struct spa_format *format, + uint32_t n_params, + const struct spa_param **params, + const struct spa_port_info *info); + /** + * Send an event to the node + * \param event the event to send + */ + void (*event) (void *object, struct spa_event *event); + /** + * Destroy the client_node + */ + void (*destroy) (void *object); +}; + +#define pw_client_node_do_done(r,...) ((struct pw_client_node_methods*)r->iface->methods)->done(r,__VA_ARGS__) +#define pw_client_node_do_update(r,...) ((struct pw_client_node_methods*)r->iface->methods)->update(r,__VA_ARGS__) +#define pw_client_node_do_port_update(r,...) ((struct pw_client_node_methods*)r->iface->methods)->port_update(r,__VA_ARGS__) +#define pw_client_node_do_event(r,...) ((struct pw_client_node_methods*)r->iface->methods)->event(r,__VA_ARGS__) +#define pw_client_node_do_destroy(r) ((struct pw_client_node_methods*)r->iface->methods)->destroy(r) + +#define PW_CLIENT_NODE_EVENT_SET_PROPS 0 +#define PW_CLIENT_NODE_EVENT_EVENT 1 +#define PW_CLIENT_NODE_EVENT_ADD_PORT 2 +#define PW_CLIENT_NODE_EVENT_REMOVE_PORT 3 +#define PW_CLIENT_NODE_EVENT_SET_FORMAT 4 +#define PW_CLIENT_NODE_EVENT_SET_PARAM 5 +#define PW_CLIENT_NODE_EVENT_ADD_MEM 6 +#define PW_CLIENT_NODE_EVENT_USE_BUFFERS 7 +#define PW_CLIENT_NODE_EVENT_NODE_COMMAND 8 +#define PW_CLIENT_NODE_EVENT_PORT_COMMAND 9 +#define PW_CLIENT_NODE_EVENT_TRANSPORT 10 +#define PW_CLIENT_NODE_EVENT_NUM 11 + +/** \ref pw_client_node events */ +struct pw_client_node_events { + /** + * Notify of a property change + * + * When the server configures the properties on the node + * this event is sent + * + * \param seq a sequence number + * \param props the props to set + */ + void (*set_props) (void *object, + uint32_t seq, + const struct spa_props *props); + /** + * Receive an event from the client node + * \param event the received event */ + void (*event) (void *object, const struct spa_event *event); + /** + * A new port was added to the node + * + * The server can at any time add a port to the node when there + * are free ports available. + * + * \param seq a sequence number + * \param direction the direction of the port + * \param port_id the new port id + */ + void (*add_port) (void *object, + uint32_t seq, + enum spa_direction direction, + uint32_t port_id); + /** + * A port was removed from the node + * + * \param seq a sequence number + * \param direction a port direction + * \param port_id the remove port id + */ + void (*remove_port) (void *object, + uint32_t seq, + enum spa_direction direction, + uint32_t port_id); + /** + * A format was configured on the port + * + * \param seq a sequence number + * \param direction a port direction + * \param port_id the port id + * \param flags flags used when setting the format + * \param format the new format + */ + void (*set_format) (void *object, + uint32_t seq, + enum spa_direction direction, + uint32_t port_id, + uint32_t flags, + const struct spa_format *format); + /** + * A parameter was configured on the port + * + * \param seq a sequence number + * \param direction a port direction + * \param port_id the port id + * \param param the new param + */ + void (*set_param) (void *object, + uint32_t seq, + enum spa_direction direction, + uint32_t port_id, + const struct spa_param *param); + /** + * Memory was added for a port + * + * \param direction a port direction + * \param port_id the port id + * \param mem_id the id of the memory + * \param type the memory type + * \param memfd the fd of the memory + * \param flags flags for the \a memfd + * \param offset valid offset of mapped memory from \a memfd + * \param size valid size of mapped memory from \a memfd + */ + void (*add_mem) (void *object, + enum spa_direction direction, + uint32_t port_id, + uint32_t mem_id, + uint32_t type, + int memfd, + uint32_t flags, + uint32_t offset, + uint32_t size); + /** + * Notify the port of buffers + * + * \param seq a sequence number + * \param direction a port direction + * \param port_id the port id + * \param n_buffer the number of buffers + * \param buffers and array of buffer descriptions + */ + void (*use_buffers) (void *object, + uint32_t seq, + enum spa_direction direction, + uint32_t port_id, + uint32_t n_buffers, + struct pw_client_node_buffer *buffers); + /** + * Notify of a new node command + * + * \param seq a sequence number + * \param command the command + */ + void (*node_command) (void *object, uint32_t seq, const struct spa_command *command); + /** + * Notify of a new port command + * + * \param direction a port direction + * \param port_id the port id + * \param command the command + */ + void (*port_command) (void *object, + enum spa_direction direction, + uint32_t port_id, + const struct spa_command *command); + + /** + * Notify of a new transport area + * + * The transport area is used to exchange real-time commands between + * the client and the server. + * + * \param readfd fd for signal data can be read + * \param writefd fd for signal data can be written + * \param memfd the memory fd of the area + * \param offset the offset to map + * \param size the size to map + */ + void (*transport) (void *object, + int readfd, + int writefd, + int memfd, + uint32_t offset, + uint32_t size); +}; + +#define pw_client_node_notify_set_props(r,...) ((struct pw_client_node_events*)r->iface->events)->props(r,__VA_ARGS__) +#define pw_client_node_notify_event(r,...) ((struct pw_client_node_events*)r->iface->events)->event(r,__VA_ARGS__) +#define pw_client_node_notify_add_port(r,...) ((struct pw_client_node_events*)r->iface->events)->add_port(r,__VA_ARGS__) +#define pw_client_node_notify_remove_port(r,...) ((struct pw_client_node_events*)r->iface->events)->remove_port(r,__VA_ARGS__) +#define pw_client_node_notify_set_format(r,...) ((struct pw_client_node_events*)r->iface->events)->set_format(r,__VA_ARGS__) +#define pw_client_node_notify_set_param(r,...) ((struct pw_client_node_events*)r->iface->events)->set_param(r,__VA_ARGS__) +#define pw_client_node_notify_add_mem(r,...) ((struct pw_client_node_events*)r->iface->events)->add_mem(r,__VA_ARGS__) +#define pw_client_node_notify_use_buffers(r,...) ((struct pw_client_node_events*)r->iface->events)->use_buffers(r,__VA_ARGS__) +#define pw_client_node_notify_node_command(r,...) ((struct pw_client_node_events*)r->iface->events)->node_command(r,__VA_ARGS__) +#define pw_client_node_notify_port_command(r,...) ((struct pw_client_node_events*)r->iface->events)->port_command(r,__VA_ARGS__) +#define pw_client_node_notify_transport(r,...) ((struct pw_client_node_events*)r->iface->events)->transport(r,__VA_ARGS__) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __PIPEWIRE_EXT_CLIENT_NODE_H__ */ diff --git a/pipewire/modules/extension-client-node.c b/pipewire/modules/extension-client-node.c new file mode 100644 index 000000000..ba2885fad --- /dev/null +++ b/pipewire/modules/extension-client-node.c @@ -0,0 +1,66 @@ +/* PipeWire + * Copyright (C) 2017 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "config.h" + +#include "pipewire/client/interfaces.h" +#include "pipewire/client/context.h" +#include "pipewire/client/extension.h" + +struct pw_protocol *pw_protocol_native_ext_client_node_init(void); + +struct impl { + struct pw_context *context; + struct pw_properties *properties; +}; + +static struct impl *extension_new(struct pw_context *context, struct pw_properties *properties) +{ + struct impl *impl; + + impl = calloc(1, sizeof(struct impl)); + pw_log_debug("extension %p: new", impl); + + impl->context = context; + impl->properties = properties; + + pw_protocol_native_ext_client_node_init(); + + return impl; +} + +#if 0 +static void extension_destroy(struct impl *impl) +{ + pw_log_debug("extension %p: destroy", impl); + + free(impl); +} +#endif + +bool pipewire__extension_init(struct pw_extension *extension, const char *args) +{ + extension_new(extension->context, NULL); + return true; +} diff --git a/pipewire/modules/extension-protocol-native.c b/pipewire/modules/extension-protocol-native.c new file mode 100644 index 000000000..a7f439ad5 --- /dev/null +++ b/pipewire/modules/extension-protocol-native.c @@ -0,0 +1,66 @@ +/* PipeWire + * Copyright (C) 2017 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "config.h" + +#include "pipewire/client/interfaces.h" +#include "pipewire/client/context.h" +#include "pipewire/client/extension.h" + +struct pw_protocol *pw_protocol_native_init(void); + +struct impl { + struct pw_context *context; + struct pw_properties *properties; +}; + +static struct impl *extension_new(struct pw_context *context, struct pw_properties *properties) +{ + struct impl *impl; + + impl = calloc(1, sizeof(struct impl)); + pw_log_debug("extension %p: new", impl); + + impl->context = context; + impl->properties = properties; + + pw_protocol_native_init(); + + return impl; +} + +#if 0 +static void extension_destroy(struct impl *impl) +{ + pw_log_debug("extension %p: destroy", impl); + + free(impl); +} +#endif + +bool pipewire__extension_init(struct pw_extension *extension, const char *args) +{ + extension_new(extension->context, NULL); + return true; +} diff --git a/pipewire/modules/meson.build b/pipewire/modules/meson.build index 35153aadf..6f9fab488 100644 --- a/pipewire/modules/meson.build +++ b/pipewire/modules/meson.build @@ -33,7 +33,10 @@ pipewire_module_mixer = shared_library('pipewire-module-mixer', [ 'module-mixer. ) pipewire_module_client_node = shared_library('pipewire-module-client-node', - [ 'module-client-node.c', 'module-client-node/client-node.c' ], + [ 'module-client-node.c', + 'module-client-node/client-node.c', + 'module-client-node/protocol-native.c', + 'extension-client-node.c', ], c_args : pipewire_module_c_args, include_directories : [configinc, spa_inc], link_with : spalib, @@ -51,7 +54,10 @@ pipewire_module_client_node = shared_library('pipewire-module-client-node', # dependencies : [glib_dep, gio_dep, mathlib, dl_lib, pipewire_dep, pipewirecore_dep], #) -pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native', [ 'module-protocol-native.c' ], +pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native', + [ 'module-protocol-native.c', + 'module-protocol-native/protocol-native.c', + 'extension-protocol-native.c' ], c_args : pipewire_module_c_args, include_directories : [configinc, spa_inc], link_with : spalib, diff --git a/pipewire/modules/module-client-node.c b/pipewire/modules/module-client-node.c index a9cef8682..df86505e8 100644 --- a/pipewire/modules/module-client-node.c +++ b/pipewire/modules/module-client-node.c @@ -29,6 +29,8 @@ #include "pipewire/server/module.h" #include "module-client-node/client-node.h" +struct pw_protocol *pw_protocol_native_ext_client_node_init(void); + struct impl { struct pw_node_factory this; struct pw_properties *properties; @@ -69,6 +71,8 @@ static struct impl *module_new(struct pw_core *core, struct pw_properties *prope pw_signal_init(&impl->this.destroy_signal); impl->this.create_node = create_node; + pw_protocol_native_ext_client_node_init(); + spa_list_insert(core->node_factory_list.prev, &impl->this.link); pw_core_add_global(core, NULL, core->type.node_factory, 0, impl, NULL, &impl->this.global); diff --git a/pipewire/modules/module-client-node/client-node.h b/pipewire/modules/module-client-node/client-node.h index fc8fb99e9..1d6754e7e 100644 --- a/pipewire/modules/module-client-node/client-node.h +++ b/pipewire/modules/module-client-node/client-node.h @@ -21,14 +21,12 @@ #define __PIPEWIRE_CLIENT_NODE_H__ #include +#include #ifdef __cplusplus extern "C" { #endif -#define PIPEWIRE_TYPE__ClientNode PIPEWIRE_TYPE_NODE_BASE "Client" -#define PIPEWIRE_TYPE_CLIENT_NODE_BASE PIPEWIRE_TYPE__ClientNode ":" - /** \class pw_client_node * * PipeWire client node interface diff --git a/pipewire/server/protocol-native.c b/pipewire/modules/module-client-node/protocol-native.c similarity index 51% rename from pipewire/server/protocol-native.c rename to pipewire/modules/module-client-node/protocol-native.c index b8f9134e1..7d0c72e8b 100644 --- a/pipewire/server/protocol-native.c +++ b/pipewire/modules/module-client-node/protocol-native.c @@ -17,20 +17,25 @@ * Boston, MA 02110-1301, USA. */ +#include #include "spa/pod-iter.h" +#include "pipewire/client/pipewire.h" #include "pipewire/client/interfaces.h" -#include "pipewire/server/resource.h" -#include "pipewire/server/protocol-native.h" +#include "pipewire/client/protocol.h" +#include "pipewire/client/connection.h" +#include "pipewire/server/client.h" +#include "pipewire/extensions/client-node.h" /** \cond */ -typedef bool(*demarshal_func_t) (void *object, void *data, size_t size); - struct builder { struct spa_pod_builder b; struct pw_connection *connection; }; + +typedef bool(*demarshal_func_t) (void *object, void *data, size_t size); + /** \endcond */ static uint32_t write_pod(struct spa_pod_builder *b, uint32_t ref, const void *data, uint32_t size) @@ -46,7 +51,25 @@ static uint32_t write_pod(struct spa_pod_builder *b, uint32_t ref, const void *d return ref; } -static void core_update_map(struct pw_client *client) +static void core_update_map_client(struct pw_context *context) +{ + uint32_t diff, base, i; + const char **types; + + base = context->n_types; + diff = spa_type_map_get_size(context->type.map) - base; + if (diff == 0) + return; + + types = alloca(diff * sizeof(char *)); + for (i = 0; i < diff; i++, base++) + types[i] = spa_type_map_get_type(context->type.map, base); + + pw_core_do_update_types(context->core_proxy, context->n_types, diff, types); + context->n_types += diff; +} + +static void core_update_map_server(struct pw_client *client) { uint32_t diff, base, i; struct pw_core *core = client->core; @@ -65,402 +88,408 @@ static void core_update_map(struct pw_client *client) client->n_types += diff; } -static void core_marshal_info(void *object, struct pw_core_info *info) + +static void +client_node_marshal_done(void *object, int seq, int res) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - uint32_t i, n_items; - - core_update_map(resource->client); - - n_items = info->props ? info->props->n_items : 0; - - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f, - SPA_POD_TYPE_INT, info->id, - SPA_POD_TYPE_LONG, info->change_mask, - SPA_POD_TYPE_STRING, info->user_name, - SPA_POD_TYPE_STRING, info->host_name, - SPA_POD_TYPE_STRING, info->version, - SPA_POD_TYPE_STRING, info->name, - SPA_POD_TYPE_INT, info->cookie, SPA_POD_TYPE_INT, n_items, 0); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRING, info->props->items[i].key, - SPA_POD_TYPE_STRING, info->props->items[i].value, 0); - } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); - - pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_INFO, b.b.offset); -} - -static void core_marshal_done(void *object, uint32_t seq) -{ - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; + struct pw_proxy *proxy = object; + struct pw_connection *connection = proxy->context->protocol_private; struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + if (connection == NULL) + return; - spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq); - - pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_DONE, b.b.offset); -} - -static void core_marshal_error(void *object, uint32_t id, int res, const char *error, ...) -{ - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - char buffer[128]; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - va_list ap; - - core_update_map(resource->client); - - va_start(ap, error); - vsnprintf(buffer, sizeof(buffer), error, ap); - va_end(ap); + core_update_map_client(proxy->context); spa_pod_builder_struct(&b.b, &f, - SPA_POD_TYPE_INT, id, - SPA_POD_TYPE_INT, res, SPA_POD_TYPE_STRING, buffer); + SPA_POD_TYPE_INT, seq, + SPA_POD_TYPE_INT, res); - pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_ERROR, b.b.offset); + pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_DONE, b.b.offset); } -static void core_marshal_remove_id(void *object, uint32_t id) + + +static void +client_node_marshal_update(void *object, + uint32_t change_mask, + uint32_t max_input_ports, + uint32_t max_output_ports, const struct spa_props *props) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; + struct pw_proxy *proxy = object; + struct pw_connection *connection = proxy->context->protocol_private; struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + if (connection == NULL) + return; - spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, id); + core_update_map_client(proxy->context); - pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_REMOVE_ID, b.b.offset); + spa_pod_builder_struct(&b.b, &f, + SPA_POD_TYPE_INT, change_mask, + SPA_POD_TYPE_INT, max_input_ports, + SPA_POD_TYPE_INT, max_output_ports, SPA_POD_TYPE_POD, props); + + pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_UPDATE, b.b.offset); } static void -core_marshal_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types) +client_node_marshal_port_update(void *object, + enum spa_direction direction, + uint32_t port_id, + uint32_t change_mask, + uint32_t n_possible_formats, + const struct spa_format **possible_formats, + const struct spa_format *format, + uint32_t n_params, + const struct spa_param **params, const struct spa_port_info *info) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; + struct pw_proxy *proxy = object; + struct pw_connection *connection = proxy->context->protocol_private; struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - uint32_t i; - - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f, - SPA_POD_TYPE_INT, first_id, SPA_POD_TYPE_INT, n_types, 0); - - for (i = 0; i < n_types; i++) { - spa_pod_builder_add(&b.b, SPA_POD_TYPE_STRING, types[i], 0); - } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); - - pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_UPDATE_TYPES, b.b.offset); -} - -static bool core_demarshal_client_update(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_dict props; - struct spa_pod_iter it; - uint32_t i; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &props.n_items, 0)) - return false; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - for (i = 0; i < props.n_items; i++) { - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_STRING, &props.items[i].key, - SPA_POD_TYPE_STRING, &props.items[i].value, 0)) - return false; - } - ((struct pw_core_methods *) resource->implementation)->client_update(resource, &props); - return true; -} - -static bool core_demarshal_sync(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_pod_iter it; - uint32_t seq; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, 0)) - return false; - - ((struct pw_core_methods *) resource->implementation)->sync(resource, seq); - return true; -} - -static bool core_demarshal_get_registry(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_pod_iter it; - int32_t new_id; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) - return false; - - ((struct pw_core_methods *) resource->implementation)->get_registry(resource, new_id); - return true; -} - -static bool core_demarshal_create_node(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_pod_iter it; - uint32_t new_id, i; - const char *factory_name, *name; - struct spa_dict props; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_STRING, &factory_name, - SPA_POD_TYPE_STRING, &name, SPA_POD_TYPE_INT, &props.n_items, 0)) - return false; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - for (i = 0; i < props.n_items; i++) { - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_STRING, &props.items[i].key, - SPA_POD_TYPE_STRING, &props.items[i].value, 0)) - return false; - } - if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) - return false; - - ((struct pw_core_methods *) resource->implementation)->create_node(resource, - factory_name, - name, &props, new_id); - return true; -} - -static bool core_demarshal_create_link(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_pod_iter it; - uint32_t new_id, i; - uint32_t output_node_id, output_port_id, input_node_id, input_port_id; - struct spa_format *filter = NULL; - struct spa_dict props; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &resource->client->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &output_node_id, - SPA_POD_TYPE_INT, &output_port_id, - SPA_POD_TYPE_INT, &input_node_id, - SPA_POD_TYPE_INT, &input_port_id, - -SPA_POD_TYPE_OBJECT, &filter, - SPA_POD_TYPE_INT, &props.n_items, 0)) - return false; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - for (i = 0; i < props.n_items; i++) { - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_STRING, &props.items[i].key, - SPA_POD_TYPE_STRING, &props.items[i].value, 0)) - return false; - } - if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) - return false; - - ((struct pw_core_methods *) resource->implementation)->create_link(resource, - output_node_id, - output_port_id, - input_node_id, - input_port_id, - filter, - &props, - new_id); - return true; -} - -static bool core_demarshal_update_types(void *object, void *data, size_t size) -{ - struct pw_resource *resource = object; - struct spa_pod_iter it; - uint32_t first_id, n_types; - const char **types; + struct spa_pod_frame f[2]; int i; - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &first_id, SPA_POD_TYPE_INT, &n_types, 0)) - return false; + if (connection == NULL) + return; - types = alloca(n_types * sizeof(char *)); - for (i = 0; i < n_types; i++) { - if (!spa_pod_iter_get(&it, SPA_POD_TYPE_STRING, &types[i], 0)) - return false; + core_update_map_client(proxy->context); + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f[0], + SPA_POD_TYPE_INT, direction, + SPA_POD_TYPE_INT, port_id, + SPA_POD_TYPE_INT, change_mask, SPA_POD_TYPE_INT, n_possible_formats, 0); + + for (i = 0; i < n_possible_formats; i++) + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, possible_formats[i], 0); + + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, format, SPA_POD_TYPE_INT, n_params, 0); + + for (i = 0; i < n_params; i++) { + const struct spa_param *p = params[i]; + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, p, 0); } - ((struct pw_core_methods *) resource->implementation)->update_types(resource, first_id, - n_types, types); - return true; -} -static void registry_marshal_global(void *object, uint32_t id, const char *type, uint32_t version) -{ - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; + if (info) { + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f[1], + SPA_POD_TYPE_INT, info->flags, SPA_POD_TYPE_INT, info->rate, 0); + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f[1], 0); + } else { + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, NULL, 0); + } + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f[0], 0); - core_update_map(resource->client); - - spa_pod_builder_struct(&b.b, &f, - SPA_POD_TYPE_INT, id, - SPA_POD_TYPE_STRING, type, - SPA_POD_TYPE_INT, version); - - pw_connection_end_write(connection, resource->id, PW_REGISTRY_EVENT_GLOBAL, b.b.offset); -} - -static void registry_marshal_global_remove(void *object, uint32_t id) -{ - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - - core_update_map(resource->client); - - spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, id); - - pw_connection_end_write(connection, resource->id, PW_REGISTRY_EVENT_GLOBAL_REMOVE, + pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_PORT_UPDATE, b.b.offset); } -static bool registry_demarshal_bind(void *object, void *data, size_t size) +static void client_node_marshal_event_method(void *object, struct spa_event *event) { - struct pw_resource *resource = object; + struct pw_proxy *proxy = object; + struct pw_connection *connection = proxy->context->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + if (connection == NULL) + return; + + core_update_map_client(proxy->context); + + spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_POD, event); + + pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_EVENT, b.b.offset); +} + +static void client_node_marshal_destroy(void *object) +{ + struct pw_proxy *proxy = object; + struct pw_connection *connection = proxy->context->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + if (connection == NULL) + return; + + core_update_map_client(proxy->context); + + spa_pod_builder_struct(&b.b, &f, 0); + + pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_DESTROY, b.b.offset); +} + +static bool client_node_demarshal_set_props(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; struct spa_pod_iter it; - uint32_t id, version, new_id; + uint32_t seq; + const struct spa_props *props = NULL; if (!spa_pod_iter_struct(&it, data, size) || !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &id, - SPA_POD_TYPE_INT, &version, - SPA_POD_TYPE_INT, &new_id, 0)) + SPA_POD_TYPE_INT, &seq, + -SPA_POD_TYPE_OBJECT, &props, 0)) return false; - ((struct pw_registry_methods *) resource->implementation)->bind(resource, id, version, new_id); + ((struct pw_client_node_events *) proxy->implementation)->set_props(proxy, seq, props); return true; } -static void module_marshal_info(void *object, struct pw_module_info *info) +static bool client_node_demarshal_event_event(void *object, void *data, size_t size) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - uint32_t i, n_items; + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + const struct spa_event *event; - core_update_map(resource->client); + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0)) + return false; - n_items = info->props ? info->props->n_items : 0; - - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f, - SPA_POD_TYPE_INT, info->id, - SPA_POD_TYPE_LONG, info->change_mask, - SPA_POD_TYPE_STRING, info->name, - SPA_POD_TYPE_STRING, info->filename, - SPA_POD_TYPE_STRING, info->args, SPA_POD_TYPE_INT, n_items, 0); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRING, info->props->items[i].key, - SPA_POD_TYPE_STRING, info->props->items[i].value, 0); - } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); - - pw_connection_end_write(connection, resource->id, PW_MODULE_EVENT_INFO, b.b.offset); + ((struct pw_client_node_events *) proxy->implementation)->event(proxy, event); + return true; } -static void node_marshal_info(void *object, struct pw_node_info *info) +static bool client_node_demarshal_add_port(void *object, void *data, size_t size) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - uint32_t i, n_items; + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + int32_t seq, direction, port_id; - core_update_map(resource->client); + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &seq, + SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) + return false; - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f, - SPA_POD_TYPE_INT, info->id, - SPA_POD_TYPE_LONG, info->change_mask, - SPA_POD_TYPE_STRING, info->name, - SPA_POD_TYPE_INT, info->max_input_ports, - SPA_POD_TYPE_INT, info->n_input_ports, - SPA_POD_TYPE_INT, info->n_input_formats, 0); - - for (i = 0; i < info->n_input_formats; i++) - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, info->input_formats[i], 0); - - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_INT, info->max_output_ports, - SPA_POD_TYPE_INT, info->n_output_ports, - SPA_POD_TYPE_INT, info->n_output_formats, 0); - - for (i = 0; i < info->n_output_formats; i++) - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, info->output_formats[i], 0); - - n_items = info->props ? info->props->n_items : 0; - - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_INT, info->state, - SPA_POD_TYPE_STRING, info->error, SPA_POD_TYPE_INT, n_items, 0); - - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRING, info->props->items[i].key, - SPA_POD_TYPE_STRING, info->props->items[i].value, 0); - } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); - - pw_connection_end_write(connection, resource->id, PW_NODE_EVENT_INFO, b.b.offset); + ((struct pw_client_node_events *) proxy->implementation)->add_port(proxy, seq, direction, + port_id); + return true; } -static void client_marshal_info(void *object, struct pw_client_info *info) +static bool client_node_demarshal_remove_port(void *object, void *data, size_t size) { - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - uint32_t i, n_items; + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + int32_t seq, direction, port_id; - core_update_map(resource->client); + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &seq, + SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) + return false; - n_items = info->props ? info->props->n_items : 0; + ((struct pw_client_node_events *) proxy->implementation)->remove_port(proxy, seq, direction, + port_id); + return true; +} - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f, - SPA_POD_TYPE_INT, info->id, - SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_INT, n_items, 0); +static bool client_node_demarshal_set_format(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + uint32_t seq, direction, port_id, flags; + const struct spa_format *format = NULL; - for (i = 0; i < n_items; i++) { - spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRING, info->props->items[i].key, - SPA_POD_TYPE_STRING, info->props->items[i].value, 0); + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &seq, + SPA_POD_TYPE_INT, &direction, + SPA_POD_TYPE_INT, &port_id, + SPA_POD_TYPE_INT, &flags, + -SPA_POD_TYPE_OBJECT, &format, 0)) + return false; + + ((struct pw_client_node_events *) proxy->implementation)->set_format(proxy, seq, direction, + port_id, flags, + format); + return true; +} + +static bool client_node_demarshal_set_param(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + uint32_t seq, direction, port_id; + const struct spa_param *param = NULL; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &seq, + SPA_POD_TYPE_INT, &direction, + SPA_POD_TYPE_INT, &port_id, + -SPA_POD_TYPE_OBJECT, ¶m, 0)) + return false; + + ((struct pw_client_node_events *) proxy->implementation)->set_param(proxy, seq, direction, + port_id, param); + return true; +} + +static bool client_node_demarshal_add_mem(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + struct pw_connection *connection = proxy->context->protocol_private; + uint32_t direction, port_id, mem_id, type, memfd_idx, flags, offset, sz; + int memfd; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &direction, + SPA_POD_TYPE_INT, &port_id, + SPA_POD_TYPE_INT, &mem_id, + SPA_POD_TYPE_ID, &type, + SPA_POD_TYPE_INT, &memfd_idx, + SPA_POD_TYPE_INT, &flags, + SPA_POD_TYPE_INT, &offset, SPA_POD_TYPE_INT, &sz, 0)) + return false; + + memfd = pw_connection_get_fd(connection, memfd_idx); + + ((struct pw_client_node_events *) proxy->implementation)->add_mem(proxy, + direction, + port_id, + mem_id, + type, + memfd, flags, offset, sz); + return true; +} + +static bool client_node_demarshal_use_buffers(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + uint32_t seq, direction, port_id, n_buffers, data_id; + struct pw_client_node_buffer *buffers; + int i, j; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &seq, + SPA_POD_TYPE_INT, &direction, + SPA_POD_TYPE_INT, &port_id, SPA_POD_TYPE_INT, &n_buffers, 0)) + return false; + + buffers = alloca(sizeof(struct pw_client_node_buffer) * n_buffers); + for (i = 0; i < n_buffers; i++) { + struct spa_buffer *buf = buffers[i].buffer = alloca(sizeof(struct spa_buffer)); + + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &buffers[i].mem_id, + SPA_POD_TYPE_INT, &buffers[i].offset, + SPA_POD_TYPE_INT, &buffers[i].size, + SPA_POD_TYPE_INT, &buf->id, + SPA_POD_TYPE_INT, &buf->n_metas, 0)) + return false; + + buf->metas = alloca(sizeof(struct spa_meta) * buf->n_metas); + for (j = 0; j < buf->n_metas; j++) { + struct spa_meta *m = &buf->metas[j]; + + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_ID, &m->type, + SPA_POD_TYPE_INT, &m->size, 0)) + return false; + } + if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &buf->n_datas, 0)) + return false; + + buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas); + for (j = 0; j < buf->n_datas; j++) { + struct spa_data *d = &buf->datas[j]; + + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_ID, &d->type, + SPA_POD_TYPE_INT, &data_id, + SPA_POD_TYPE_INT, &d->flags, + SPA_POD_TYPE_INT, &d->mapoffset, + SPA_POD_TYPE_INT, &d->maxsize, 0)) + return false; + + d->data = SPA_UINT32_TO_PTR(data_id); + } } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); + ((struct pw_client_node_events *) proxy->implementation)->use_buffers(proxy, + seq, + direction, + port_id, + n_buffers, buffers); + return true; +} - pw_connection_end_write(connection, resource->id, PW_CLIENT_EVENT_INFO, b.b.offset); +static bool client_node_demarshal_node_command(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + const struct spa_command *command; + uint32_t seq; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, SPA_POD_TYPE_OBJECT, &command, 0)) + return false; + + ((struct pw_client_node_events *) proxy->implementation)->node_command(proxy, seq, command); + return true; +} + +static bool client_node_demarshal_port_command(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + const struct spa_command *command; + uint32_t direction, port_id; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &direction, + SPA_POD_TYPE_INT, &port_id, + SPA_POD_TYPE_OBJECT, &command, 0)) + return false; + + ((struct pw_client_node_events *) proxy->implementation)->port_command(proxy, + direction, + port_id, + command); + return true; +} + +static bool client_node_demarshal_transport(void *object, void *data, size_t size) +{ + struct pw_proxy *proxy = object; + struct spa_pod_iter it; + struct pw_connection *connection = proxy->context->protocol_private; + uint32_t ridx, widx, memfd_idx, offset, sz; + int readfd, writefd, memfd; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &ridx, + SPA_POD_TYPE_INT, &widx, + SPA_POD_TYPE_INT, &memfd_idx, + SPA_POD_TYPE_INT, &offset, + SPA_POD_TYPE_INT, &sz, 0)) + return false; + + readfd = pw_connection_get_fd(connection, ridx); + writefd = pw_connection_get_fd(connection, widx); + memfd = pw_connection_get_fd(connection, memfd_idx); + if (readfd == -1 || writefd == -1 || memfd_idx == -1) + return false; + + ((struct pw_client_node_events *) proxy->implementation)->transport(proxy, + readfd, writefd, + memfd, offset, sz); + return true; } static void @@ -471,7 +500,7 @@ client_node_marshal_set_props(void *object, uint32_t seq, const struct spa_props struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, @@ -481,14 +510,14 @@ client_node_marshal_set_props(void *object, uint32_t seq, const struct spa_props b.b.offset); } -static void client_node_marshal_event(void *object, const struct spa_event *event) +static void client_node_marshal_event_event(void *object, const struct spa_event *event) { struct pw_resource *resource = object; struct pw_connection *connection = resource->client->protocol_private; struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_POD, event); @@ -504,7 +533,7 @@ client_node_marshal_add_port(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, @@ -523,7 +552,7 @@ client_node_marshal_remove_port(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, @@ -546,7 +575,7 @@ client_node_marshal_set_format(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, @@ -571,7 +600,7 @@ client_node_marshal_set_param(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, @@ -596,7 +625,7 @@ client_node_marshal_add_mem(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, direction, @@ -623,7 +652,7 @@ client_node_marshal_use_buffers(void *object, struct spa_pod_frame f; uint32_t i, j; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_add(&b.b, SPA_POD_TYPE_STRUCT, &f, @@ -670,7 +699,7 @@ client_node_marshal_node_command(void *object, uint32_t seq, const struct spa_co struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq, SPA_POD_TYPE_POD, command); @@ -689,7 +718,7 @@ client_node_marshal_port_command(void *object, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, direction, @@ -708,7 +737,7 @@ static void client_node_marshal_transport(void *object, int readfd, int writefd, struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; - core_update_map(resource->client); + core_update_map_server(resource->client); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, pw_connection_add_fd(connection, readfd), @@ -817,7 +846,7 @@ static bool client_node_demarshal_port_update(void *object, void *data, size_t s return true; } -static bool client_node_demarshal_event(void *object, void *data, size_t size) +static bool client_node_demarshal_event_method(void *object, void *data, size_t size) { struct pw_resource *resource = object; struct spa_pod_iter it; @@ -844,111 +873,46 @@ static bool client_node_demarshal_destroy(void *object, void *data, size_t size) return true; } -static void link_marshal_info(void *object, struct pw_link_info *info) -{ - struct pw_resource *resource = object; - struct pw_connection *connection = resource->client->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - - core_update_map(resource->client); - - spa_pod_builder_struct(&b.b, &f, - SPA_POD_TYPE_INT, info->id, - SPA_POD_TYPE_LONG, info->change_mask, - SPA_POD_TYPE_INT, info->output_node_id, - SPA_POD_TYPE_INT, info->output_port_id, - SPA_POD_TYPE_INT, info->input_node_id, - SPA_POD_TYPE_INT, info->input_port_id, - SPA_POD_TYPE_POD, info->format); - - pw_connection_end_write(connection, resource->id, PW_LINK_EVENT_INFO, b.b.offset); -} - -static const demarshal_func_t pw_protocol_native_server_core_demarshal[PW_CORE_METHOD_NUM] = { - &core_demarshal_update_types, - &core_demarshal_sync, - &core_demarshal_get_registry, - &core_demarshal_client_update, - &core_demarshal_create_node, - &core_demarshal_create_link +static const struct pw_client_node_methods pw_protocol_native_client_client_node_methods = { + &client_node_marshal_done, + &client_node_marshal_update, + &client_node_marshal_port_update, + &client_node_marshal_event_method, + &client_node_marshal_destroy }; -static const struct pw_core_events pw_protocol_native_server_core_events = { - &core_marshal_update_types, - &core_marshal_done, - &core_marshal_error, - &core_marshal_remove_id, - &core_marshal_info +static const demarshal_func_t pw_protocol_native_client_client_node_demarshal[] = { + &client_node_demarshal_set_props, + &client_node_demarshal_event_event, + &client_node_demarshal_add_port, + &client_node_demarshal_remove_port, + &client_node_demarshal_set_format, + &client_node_demarshal_set_param, + &client_node_demarshal_add_mem, + &client_node_demarshal_use_buffers, + &client_node_demarshal_node_command, + &client_node_demarshal_port_command, + &client_node_demarshal_transport }; -const struct pw_interface pw_protocol_native_server_core_interface = { - PIPEWIRE_TYPE__Core, - PW_VERSION_CORE, - PW_CORE_METHOD_NUM, pw_protocol_native_server_core_demarshal, - PW_CORE_EVENT_NUM, &pw_protocol_native_server_core_events, -}; - -static const demarshal_func_t pw_protocol_native_server_registry_demarshal[] = { - ®istry_demarshal_bind, -}; - -static const struct pw_registry_events pw_protocol_native_server_registry_events = { - ®istry_marshal_global, - ®istry_marshal_global_remove, -}; - -const struct pw_interface pw_protocol_native_server_registry_interface = { - PIPEWIRE_TYPE__Registry, - PW_VERSION_REGISTRY, - PW_REGISTRY_METHOD_NUM, pw_protocol_native_server_registry_demarshal, - PW_REGISTRY_EVENT_NUM, &pw_protocol_native_server_registry_events, -}; - -static const struct pw_module_events pw_protocol_native_server_module_events = { - &module_marshal_info, -}; - -const struct pw_interface pw_protocol_native_server_module_interface = { - PIPEWIRE_TYPE__Module, - PW_VERSION_MODULE, - 0, NULL, - PW_MODULE_EVENT_NUM, &pw_protocol_native_server_module_events, -}; - -static const struct pw_node_events pw_protocol_native_server_node_events = { - &node_marshal_info, -}; - -const struct pw_interface pw_protocol_native_server_node_interface = { - PIPEWIRE_TYPE__Node, - PW_VERSION_NODE, - 0, NULL, - PW_NODE_EVENT_NUM, &pw_protocol_native_server_node_events, -}; - -static const struct pw_client_events pw_protocol_native_server_client_events = { - &client_marshal_info, -}; - -const struct pw_interface pw_protocol_native_server_client_interface = { - PIPEWIRE_TYPE__Client, - PW_VERSION_CLIENT, - 0, NULL, - PW_CLIENT_EVENT_NUM, &pw_protocol_native_server_client_events, +static const struct pw_interface pw_protocol_native_client_client_node_interface = { + PIPEWIRE_TYPE_NODE_BASE "Client", + PW_VERSION_CLIENT_NODE, + PW_CLIENT_NODE_METHOD_NUM, &pw_protocol_native_client_client_node_methods, + PW_CLIENT_NODE_EVENT_NUM, pw_protocol_native_client_client_node_demarshal, }; static const demarshal_func_t pw_protocol_native_server_client_node_demarshal[] = { &client_node_demarshal_done, &client_node_demarshal_update, &client_node_demarshal_port_update, - &client_node_demarshal_event, + &client_node_demarshal_event_method, &client_node_demarshal_destroy, }; static const struct pw_client_node_events pw_protocol_native_server_client_node_events = { &client_node_marshal_set_props, - &client_node_marshal_event, + &client_node_marshal_event_event, &client_node_marshal_add_port, &client_node_marshal_remove_port, &client_node_marshal_set_format, @@ -967,18 +931,7 @@ const struct pw_interface pw_protocol_native_server_client_node_interface = { PW_CLIENT_NODE_EVENT_NUM, &pw_protocol_native_server_client_node_events, }; -static const struct pw_link_events pw_protocol_native_server_link_events = { - &link_marshal_info, -}; - -const struct pw_interface pw_protocol_native_server_link_interface = { - PIPEWIRE_TYPE__Link, - PW_VERSION_LINK, - 0, NULL, - PW_LINK_EVENT_NUM, &pw_protocol_native_server_link_events, -}; - -struct pw_protocol *pw_protocol_native_server_init(void) +struct pw_protocol *pw_protocol_native_ext_client_node_init(void) { static bool init = false; struct pw_protocol *protocol; @@ -989,26 +942,8 @@ struct pw_protocol *pw_protocol_native_server_init(void) return protocol; pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_core_interface); - pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_registry_interface); - pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_module_interface); - pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_node_interface); - pw_protocol_add_interfaces(protocol, - NULL, + &pw_protocol_native_client_client_node_interface, &pw_protocol_native_server_client_node_interface); - pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_client_interface); - pw_protocol_add_interfaces(protocol, - NULL, - &pw_protocol_native_server_link_interface); init = true; diff --git a/pipewire/modules/module-protocol-native.c b/pipewire/modules/module-protocol-native.c index 2c1ae94b6..749531e6c 100644 --- a/pipewire/modules/module-protocol-native.c +++ b/pipewire/modules/module-protocol-native.c @@ -34,7 +34,6 @@ #include "pipewire/client/interfaces.h" #include "pipewire/server/core.h" -#include "pipewire/server/protocol-native.h" #include "pipewire/server/node.h" #include "pipewire/server/module.h" #include "pipewire/server/client.h" @@ -51,6 +50,8 @@ #define LOCK_SUFFIX ".lock" #define LOCK_SUFFIXLEN 5 +struct pw_protocol *pw_protocol_native_init(void); + typedef bool(*demarshal_func_t) (void *object, void *data, size_t size); struct socket { @@ -69,6 +70,7 @@ struct impl { struct pw_core *core; struct spa_list link; + struct pw_protocol *protocol; struct pw_properties *properties; struct spa_list socket_list; @@ -217,7 +219,7 @@ static struct native_client *client_new(struct impl *impl, int fd) if (this->connection == NULL) goto no_connection; - client->protocol = pw_protocol_native_server_init(); + client->protocol = impl->protocol; client->protocol_private = this->connection; this->client = client; @@ -397,6 +399,7 @@ static struct impl *pw_protocol_native_new(struct pw_core *core, struct pw_prope impl->core = core; impl->properties = properties; + impl->protocol = pw_protocol_native_init(); name = NULL; if (impl->properties) diff --git a/pipewire/client/protocol-native.c b/pipewire/modules/module-protocol-native/protocol-native.c similarity index 55% rename from pipewire/client/protocol-native.c rename to pipewire/modules/module-protocol-native/protocol-native.c index 48b865b23..d3c41cbd1 100644 --- a/pipewire/client/protocol-native.c +++ b/pipewire/modules/module-protocol-native/protocol-native.c @@ -22,10 +22,10 @@ #include "spa/pod-iter.h" #include "pipewire/client/pipewire.h" -#include "pipewire/client/protocol-native.h" #include "pipewire/client/protocol.h" #include "pipewire/client/interfaces.h" #include "pipewire/client/connection.h" +#include "pipewire/server/resource.h" /** \cond */ struct builder { @@ -50,7 +50,7 @@ static uint32_t write_pod(struct spa_pod_builder *b, uint32_t ref, const void *d return ref; } -static void core_update_map(struct pw_context *context) +static void core_update_map_client(struct pw_context *context) { uint32_t diff, base, i; const char **types; @@ -68,6 +68,26 @@ static void core_update_map(struct pw_context *context) context->n_types += diff; } +static void core_update_map_server(struct pw_client *client) +{ + uint32_t diff, base, i; + struct pw_core *core = client->core; + const char **types; + + base = client->n_types; + diff = spa_type_map_get_size(core->type.map) - base; + if (diff == 0) + return; + + types = alloca(diff * sizeof(char *)); + for (i = 0; i < diff; i++, base++) + types[i] = spa_type_map_get_type(core->type.map, base); + + pw_core_notify_update_types(client->core_resource, client->n_types, diff, types); + client->n_types += diff; +} + + static void core_marshal_client_update(void *object, const struct spa_dict *props) { struct pw_proxy *proxy = object; @@ -79,7 +99,7 @@ static void core_marshal_client_update(void *object, const struct spa_dict *prop if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); n_items = props ? props->n_items : 0; @@ -105,7 +125,7 @@ static void core_marshal_sync(void *object, uint32_t seq) if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq); @@ -122,7 +142,7 @@ static void core_marshal_get_registry(void *object, uint32_t new_id) if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, new_id); @@ -143,7 +163,7 @@ core_marshal_create_node(void *object, if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); n_items = props ? props->n_items : 0; @@ -181,7 +201,7 @@ core_marshal_create_link(void *object, if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); n_items = props ? props->n_items : 0; @@ -207,7 +227,7 @@ core_marshal_create_link(void *object, } static void -core_marshal_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types) +core_marshal_update_types_client(void *object, uint32_t first_id, uint32_t n_types, const char **types) { struct pw_proxy *proxy = object; struct pw_connection *connection = proxy->context->protocol_private; @@ -306,7 +326,7 @@ static bool core_demarshal_remove_id(void *object, void *data, size_t size) return true; } -static bool core_demarshal_update_types(void *object, void *data, size_t size) +static bool core_demarshal_update_types_client(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; struct spa_pod_iter it; @@ -328,6 +348,331 @@ static bool core_demarshal_update_types(void *object, void *data, size_t size) return true; } +static void core_marshal_info(void *object, struct pw_core_info *info) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + uint32_t i, n_items; + + core_update_map_server(resource->client); + + n_items = info->props ? info->props->n_items : 0; + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f, + SPA_POD_TYPE_INT, info->id, + SPA_POD_TYPE_LONG, info->change_mask, + SPA_POD_TYPE_STRING, info->user_name, + SPA_POD_TYPE_STRING, info->host_name, + SPA_POD_TYPE_STRING, info->version, + SPA_POD_TYPE_STRING, info->name, + SPA_POD_TYPE_INT, info->cookie, SPA_POD_TYPE_INT, n_items, 0); + + for (i = 0; i < n_items; i++) { + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRING, info->props->items[i].key, + SPA_POD_TYPE_STRING, info->props->items[i].value, 0); + } + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); + + pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_INFO, b.b.offset); +} + +static void core_marshal_done(void *object, uint32_t seq) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + core_update_map_server(resource->client); + + spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, seq); + + pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_DONE, b.b.offset); +} + +static void core_marshal_error(void *object, uint32_t id, int res, const char *error, ...) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + char buffer[128]; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + va_list ap; + + core_update_map_server(resource->client); + + va_start(ap, error); + vsnprintf(buffer, sizeof(buffer), error, ap); + va_end(ap); + + spa_pod_builder_struct(&b.b, &f, + SPA_POD_TYPE_INT, id, + SPA_POD_TYPE_INT, res, SPA_POD_TYPE_STRING, buffer); + + pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_ERROR, b.b.offset); +} + +static void core_marshal_remove_id(void *object, uint32_t id) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + core_update_map_server(resource->client); + + spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, id); + + pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_REMOVE_ID, b.b.offset); +} + +static void +core_marshal_update_types_server(void *object, uint32_t first_id, uint32_t n_types, const char **types) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + uint32_t i; + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f, + SPA_POD_TYPE_INT, first_id, SPA_POD_TYPE_INT, n_types, 0); + + for (i = 0; i < n_types; i++) { + spa_pod_builder_add(&b.b, SPA_POD_TYPE_STRING, types[i], 0); + } + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); + + pw_connection_end_write(connection, resource->id, PW_CORE_EVENT_UPDATE_TYPES, b.b.offset); +} + +static bool core_demarshal_client_update(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_dict props; + struct spa_pod_iter it; + uint32_t i; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &props.n_items, 0)) + return false; + + props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_STRING, &props.items[i].key, + SPA_POD_TYPE_STRING, &props.items[i].value, 0)) + return false; + } + ((struct pw_core_methods *) resource->implementation)->client_update(resource, &props); + return true; +} + +static bool core_demarshal_sync(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + uint32_t seq; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, 0)) + return false; + + ((struct pw_core_methods *) resource->implementation)->sync(resource, seq); + return true; +} + +static bool core_demarshal_get_registry(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + int32_t new_id; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) + return false; + + ((struct pw_core_methods *) resource->implementation)->get_registry(resource, new_id); + return true; +} + +static bool core_demarshal_create_node(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + uint32_t new_id, i; + const char *factory_name, *name; + struct spa_dict props; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_STRING, &factory_name, + SPA_POD_TYPE_STRING, &name, SPA_POD_TYPE_INT, &props.n_items, 0)) + return false; + + props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_STRING, &props.items[i].key, + SPA_POD_TYPE_STRING, &props.items[i].value, 0)) + return false; + } + if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) + return false; + + ((struct pw_core_methods *) resource->implementation)->create_node(resource, + factory_name, + name, &props, new_id); + return true; +} + +static bool core_demarshal_create_link(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + uint32_t new_id, i; + uint32_t output_node_id, output_port_id, input_node_id, input_port_id; + struct spa_format *filter = NULL; + struct spa_dict props; + + if (!spa_pod_iter_struct(&it, data, size) || + !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &resource->client->types) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &output_node_id, + SPA_POD_TYPE_INT, &output_port_id, + SPA_POD_TYPE_INT, &input_node_id, + SPA_POD_TYPE_INT, &input_port_id, + -SPA_POD_TYPE_OBJECT, &filter, + SPA_POD_TYPE_INT, &props.n_items, 0)) + return false; + + props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_iter_get(&it, + SPA_POD_TYPE_STRING, &props.items[i].key, + SPA_POD_TYPE_STRING, &props.items[i].value, 0)) + return false; + } + if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0)) + return false; + + ((struct pw_core_methods *) resource->implementation)->create_link(resource, + output_node_id, + output_port_id, + input_node_id, + input_port_id, + filter, + &props, + new_id); + return true; +} + +static bool core_demarshal_update_types_server(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + uint32_t first_id, n_types; + const char **types; + int i; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &first_id, SPA_POD_TYPE_INT, &n_types, 0)) + return false; + + types = alloca(n_types * sizeof(char *)); + for (i = 0; i < n_types; i++) { + if (!spa_pod_iter_get(&it, SPA_POD_TYPE_STRING, &types[i], 0)) + return false; + } + ((struct pw_core_methods *) resource->implementation)->update_types(resource, first_id, + n_types, types); + return true; +} + +static void registry_marshal_global(void *object, uint32_t id, const char *type, uint32_t version) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + core_update_map_server(resource->client); + + spa_pod_builder_struct(&b.b, &f, + SPA_POD_TYPE_INT, id, + SPA_POD_TYPE_STRING, type, + SPA_POD_TYPE_INT, version); + + pw_connection_end_write(connection, resource->id, PW_REGISTRY_EVENT_GLOBAL, b.b.offset); +} + +static void registry_marshal_global_remove(void *object, uint32_t id) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + core_update_map_server(resource->client); + + spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, id); + + pw_connection_end_write(connection, resource->id, PW_REGISTRY_EVENT_GLOBAL_REMOVE, + b.b.offset); +} + +static bool registry_demarshal_bind(void *object, void *data, size_t size) +{ + struct pw_resource *resource = object; + struct spa_pod_iter it; + uint32_t id, version, new_id; + + if (!spa_pod_iter_struct(&it, data, size) || + !spa_pod_iter_get(&it, + SPA_POD_TYPE_INT, &id, + SPA_POD_TYPE_INT, &version, + SPA_POD_TYPE_INT, &new_id, 0)) + return false; + + ((struct pw_registry_methods *) resource->implementation)->bind(resource, id, version, new_id); + return true; +} + +static void module_marshal_info(void *object, struct pw_module_info *info) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + uint32_t i, n_items; + + core_update_map_server(resource->client); + + n_items = info->props ? info->props->n_items : 0; + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f, + SPA_POD_TYPE_INT, info->id, + SPA_POD_TYPE_LONG, info->change_mask, + SPA_POD_TYPE_STRING, info->name, + SPA_POD_TYPE_STRING, info->filename, + SPA_POD_TYPE_STRING, info->args, SPA_POD_TYPE_INT, n_items, 0); + + for (i = 0; i < n_items; i++) { + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRING, info->props->items[i].key, + SPA_POD_TYPE_STRING, info->props->items[i].value, 0); + } + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); + + pw_connection_end_write(connection, resource->id, PW_MODULE_EVENT_INFO, b.b.offset); +} + static bool module_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; @@ -357,6 +702,52 @@ static bool module_demarshal_info(void *object, void *data, size_t size) return true; } +static void node_marshal_info(void *object, struct pw_node_info *info) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + uint32_t i, n_items; + + core_update_map_server(resource->client); + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRUCT, &f, + SPA_POD_TYPE_INT, info->id, + SPA_POD_TYPE_LONG, info->change_mask, + SPA_POD_TYPE_STRING, info->name, + SPA_POD_TYPE_INT, info->max_input_ports, + SPA_POD_TYPE_INT, info->n_input_ports, + SPA_POD_TYPE_INT, info->n_input_formats, 0); + + for (i = 0; i < info->n_input_formats; i++) + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, info->input_formats[i], 0); + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_INT, info->max_output_ports, + SPA_POD_TYPE_INT, info->n_output_ports, + SPA_POD_TYPE_INT, info->n_output_formats, 0); + + for (i = 0; i < info->n_output_formats; i++) + spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, info->output_formats[i], 0); + + n_items = info->props ? info->props->n_items : 0; + + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_INT, info->state, + SPA_POD_TYPE_STRING, info->error, SPA_POD_TYPE_INT, n_items, 0); + + for (i = 0; i < n_items; i++) { + spa_pod_builder_add(&b.b, + SPA_POD_TYPE_STRING, info->props->items[i].key, + SPA_POD_TYPE_STRING, info->props->items[i].value, 0); + } + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); + + pw_connection_end_write(connection, resource->id, PW_NODE_EVENT_INFO, b.b.offset); +} + static bool node_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; @@ -410,405 +801,31 @@ static bool node_demarshal_info(void *object, void *data, size_t size) return true; } -static void -client_node_marshal_done(void *object, int seq, int res) +static void client_marshal_info(void *object, struct pw_client_info *info) { - struct pw_proxy *proxy = object; - struct pw_connection *connection = proxy->context->protocol_private; + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; struct spa_pod_frame f; + uint32_t i, n_items; - if (connection == NULL) - return; + core_update_map_server(resource->client); - core_update_map(proxy->context); - - spa_pod_builder_struct(&b.b, &f, - SPA_POD_TYPE_INT, seq, - SPA_POD_TYPE_INT, res); - - pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_DONE, b.b.offset); -} - -static void -client_node_marshal_update(void *object, - uint32_t change_mask, - uint32_t max_input_ports, - uint32_t max_output_ports, const struct spa_props *props) -{ - struct pw_proxy *proxy = object; - struct pw_connection *connection = proxy->context->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - - if (connection == NULL) - return; - - core_update_map(proxy->context); - - spa_pod_builder_struct(&b.b, &f, - SPA_POD_TYPE_INT, change_mask, - SPA_POD_TYPE_INT, max_input_ports, - SPA_POD_TYPE_INT, max_output_ports, SPA_POD_TYPE_POD, props); - - pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_UPDATE, b.b.offset); -} - -static void -client_node_marshal_port_update(void *object, - enum spa_direction direction, - uint32_t port_id, - uint32_t change_mask, - uint32_t n_possible_formats, - const struct spa_format **possible_formats, - const struct spa_format *format, - uint32_t n_params, - const struct spa_param **params, const struct spa_port_info *info) -{ - struct pw_proxy *proxy = object; - struct pw_connection *connection = proxy->context->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f[2]; - int i; - - if (connection == NULL) - return; - - core_update_map(proxy->context); + n_items = info->props ? info->props->n_items : 0; spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f[0], - SPA_POD_TYPE_INT, direction, - SPA_POD_TYPE_INT, port_id, - SPA_POD_TYPE_INT, change_mask, SPA_POD_TYPE_INT, n_possible_formats, 0); + SPA_POD_TYPE_STRUCT, &f, + SPA_POD_TYPE_INT, info->id, + SPA_POD_TYPE_LONG, info->change_mask, SPA_POD_TYPE_INT, n_items, 0); - for (i = 0; i < n_possible_formats; i++) - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, possible_formats[i], 0); - - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, format, SPA_POD_TYPE_INT, n_params, 0); - - for (i = 0; i < n_params; i++) { - const struct spa_param *p = params[i]; - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, p, 0); - } - - if (info) { + for (i = 0; i < n_items; i++) { spa_pod_builder_add(&b.b, - SPA_POD_TYPE_STRUCT, &f[1], - SPA_POD_TYPE_INT, info->flags, SPA_POD_TYPE_INT, info->rate, 0); - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f[1], 0); - } else { - spa_pod_builder_add(&b.b, SPA_POD_TYPE_POD, NULL, 0); + SPA_POD_TYPE_STRING, info->props->items[i].key, + SPA_POD_TYPE_STRING, info->props->items[i].value, 0); } - spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f[0], 0); + spa_pod_builder_add(&b.b, -SPA_POD_TYPE_STRUCT, &f, 0); - pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_PORT_UPDATE, - b.b.offset); -} - -static void client_node_marshal_event(void *object, struct spa_event *event) -{ - struct pw_proxy *proxy = object; - struct pw_connection *connection = proxy->context->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - - if (connection == NULL) - return; - - core_update_map(proxy->context); - - spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_POD, event); - - pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_EVENT, b.b.offset); -} - -static void client_node_marshal_destroy(void *object) -{ - struct pw_proxy *proxy = object; - struct pw_connection *connection = proxy->context->protocol_private; - struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; - struct spa_pod_frame f; - - if (connection == NULL) - return; - - core_update_map(proxy->context); - - spa_pod_builder_struct(&b.b, &f, 0); - - pw_connection_end_write(connection, proxy->id, PW_CLIENT_NODE_METHOD_DESTROY, b.b.offset); -} - -static bool client_node_demarshal_set_props(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - uint32_t seq; - const struct spa_props *props = NULL; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - -SPA_POD_TYPE_OBJECT, &props, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->set_props(proxy, seq, props); - return true; -} - -static bool client_node_demarshal_event(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - const struct spa_event *event; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->event(proxy, event); - return true; -} - -static bool client_node_demarshal_add_port(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - int32_t seq, direction, port_id; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->add_port(proxy, seq, direction, - port_id); - return true; -} - -static bool client_node_demarshal_remove_port(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - int32_t seq, direction, port_id; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->remove_port(proxy, seq, direction, - port_id); - return true; -} - -static bool client_node_demarshal_set_format(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - uint32_t seq, direction, port_id, flags; - const struct spa_format *format = NULL; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - SPA_POD_TYPE_INT, &direction, - SPA_POD_TYPE_INT, &port_id, - SPA_POD_TYPE_INT, &flags, - -SPA_POD_TYPE_OBJECT, &format, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->set_format(proxy, seq, direction, - port_id, flags, - format); - return true; -} - -static bool client_node_demarshal_set_param(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - uint32_t seq, direction, port_id; - const struct spa_param *param = NULL; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - SPA_POD_TYPE_INT, &direction, - SPA_POD_TYPE_INT, &port_id, - -SPA_POD_TYPE_OBJECT, ¶m, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->set_param(proxy, seq, direction, - port_id, param); - return true; -} - -static bool client_node_demarshal_add_mem(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - struct pw_connection *connection = proxy->context->protocol_private; - uint32_t direction, port_id, mem_id, type, memfd_idx, flags, offset, sz; - int memfd; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &direction, - SPA_POD_TYPE_INT, &port_id, - SPA_POD_TYPE_INT, &mem_id, - SPA_POD_TYPE_ID, &type, - SPA_POD_TYPE_INT, &memfd_idx, - SPA_POD_TYPE_INT, &flags, - SPA_POD_TYPE_INT, &offset, SPA_POD_TYPE_INT, &sz, 0)) - return false; - - memfd = pw_connection_get_fd(connection, memfd_idx); - - ((struct pw_client_node_events *) proxy->implementation)->add_mem(proxy, - direction, - port_id, - mem_id, - type, - memfd, flags, offset, sz); - return true; -} - -static bool client_node_demarshal_use_buffers(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - uint32_t seq, direction, port_id, n_buffers, data_id; - struct pw_client_node_buffer *buffers; - int i, j; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &seq, - SPA_POD_TYPE_INT, &direction, - SPA_POD_TYPE_INT, &port_id, SPA_POD_TYPE_INT, &n_buffers, 0)) - return false; - - buffers = alloca(sizeof(struct pw_client_node_buffer) * n_buffers); - for (i = 0; i < n_buffers; i++) { - struct spa_buffer *buf = buffers[i].buffer = alloca(sizeof(struct spa_buffer)); - - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &buffers[i].mem_id, - SPA_POD_TYPE_INT, &buffers[i].offset, - SPA_POD_TYPE_INT, &buffers[i].size, - SPA_POD_TYPE_INT, &buf->id, - SPA_POD_TYPE_INT, &buf->n_metas, 0)) - return false; - - buf->metas = alloca(sizeof(struct spa_meta) * buf->n_metas); - for (j = 0; j < buf->n_metas; j++) { - struct spa_meta *m = &buf->metas[j]; - - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_ID, &m->type, - SPA_POD_TYPE_INT, &m->size, 0)) - return false; - } - if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &buf->n_datas, 0)) - return false; - - buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas); - for (j = 0; j < buf->n_datas; j++) { - struct spa_data *d = &buf->datas[j]; - - if (!spa_pod_iter_get(&it, - SPA_POD_TYPE_ID, &d->type, - SPA_POD_TYPE_INT, &data_id, - SPA_POD_TYPE_INT, &d->flags, - SPA_POD_TYPE_INT, &d->mapoffset, - SPA_POD_TYPE_INT, &d->maxsize, 0)) - return false; - - d->data = SPA_UINT32_TO_PTR(data_id); - } - } - ((struct pw_client_node_events *) proxy->implementation)->use_buffers(proxy, - seq, - direction, - port_id, - n_buffers, buffers); - return true; -} - -static bool client_node_demarshal_node_command(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - const struct spa_command *command; - uint32_t seq; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, SPA_POD_TYPE_OBJECT, &command, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->node_command(proxy, seq, command); - return true; -} - -static bool client_node_demarshal_port_command(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - const struct spa_command *command; - uint32_t direction, port_id; - - if (!spa_pod_iter_struct(&it, data, size) || - !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &proxy->context->types) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &direction, - SPA_POD_TYPE_INT, &port_id, - SPA_POD_TYPE_OBJECT, &command, 0)) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->port_command(proxy, - direction, - port_id, - command); - return true; -} - -static bool client_node_demarshal_transport(void *object, void *data, size_t size) -{ - struct pw_proxy *proxy = object; - struct spa_pod_iter it; - struct pw_connection *connection = proxy->context->protocol_private; - uint32_t ridx, widx, memfd_idx, offset, sz; - int readfd, writefd, memfd; - - if (!spa_pod_iter_struct(&it, data, size) || - !spa_pod_iter_get(&it, - SPA_POD_TYPE_INT, &ridx, - SPA_POD_TYPE_INT, &widx, - SPA_POD_TYPE_INT, &memfd_idx, - SPA_POD_TYPE_INT, &offset, - SPA_POD_TYPE_INT, &sz, 0)) - return false; - - readfd = pw_connection_get_fd(connection, ridx); - writefd = pw_connection_get_fd(connection, widx); - memfd = pw_connection_get_fd(connection, memfd_idx); - if (readfd == -1 || writefd == -1 || memfd_idx == -1) - return false; - - ((struct pw_client_node_events *) proxy->implementation)->transport(proxy, - readfd, writefd, - memfd, offset, sz); - return true; + pw_connection_end_write(connection, resource->id, PW_CLIENT_EVENT_INFO, b.b.offset); } static bool client_demarshal_info(void *object, void *data, size_t size) @@ -838,6 +855,27 @@ static bool client_demarshal_info(void *object, void *data, size_t size) return true; } +static void link_marshal_info(void *object, struct pw_link_info *info) +{ + struct pw_resource *resource = object; + struct pw_connection *connection = resource->client->protocol_private; + struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection }; + struct spa_pod_frame f; + + core_update_map_server(resource->client); + + spa_pod_builder_struct(&b.b, &f, + SPA_POD_TYPE_INT, info->id, + SPA_POD_TYPE_LONG, info->change_mask, + SPA_POD_TYPE_INT, info->output_node_id, + SPA_POD_TYPE_INT, info->output_port_id, + SPA_POD_TYPE_INT, info->input_node_id, + SPA_POD_TYPE_INT, info->input_port_id, + SPA_POD_TYPE_POD, info->format); + + pw_connection_end_write(connection, resource->id, PW_LINK_EVENT_INFO, b.b.offset); +} + static bool link_demarshal_info(void *object, void *data, size_t size) { struct pw_proxy *proxy = object; @@ -902,7 +940,7 @@ static void registry_marshal_bind(void *object, uint32_t id, uint32_t version, u if (connection == NULL) return; - core_update_map(proxy->context); + core_update_map_client(proxy->context); spa_pod_builder_struct(&b.b, &f, SPA_POD_TYPE_INT, id, @@ -913,7 +951,7 @@ static void registry_marshal_bind(void *object, uint32_t id, uint32_t version, u } static const struct pw_core_methods pw_protocol_native_client_core_methods = { - &core_marshal_update_types, + &core_marshal_update_types_client, &core_marshal_sync, &core_marshal_get_registry, &core_marshal_client_update, @@ -922,7 +960,7 @@ static const struct pw_core_methods pw_protocol_native_client_core_methods = { }; static const demarshal_func_t pw_protocol_native_client_core_demarshal[PW_CORE_EVENT_NUM] = { - &core_demarshal_update_types, + &core_demarshal_update_types_client, &core_demarshal_done, &core_demarshal_error, &core_demarshal_remove_id, @@ -952,35 +990,6 @@ static const struct pw_interface pw_protocol_native_client_registry_interface = PW_REGISTRY_EVENT_NUM, pw_protocol_native_client_registry_demarshal, }; -static const struct pw_client_node_methods pw_protocol_native_client_client_node_methods = { - &client_node_marshal_done, - &client_node_marshal_update, - &client_node_marshal_port_update, - &client_node_marshal_event, - &client_node_marshal_destroy -}; - -static const demarshal_func_t pw_protocol_native_client_client_node_demarshal[] = { - &client_node_demarshal_set_props, - &client_node_demarshal_event, - &client_node_demarshal_add_port, - &client_node_demarshal_remove_port, - &client_node_demarshal_set_format, - &client_node_demarshal_set_param, - &client_node_demarshal_add_mem, - &client_node_demarshal_use_buffers, - &client_node_demarshal_node_command, - &client_node_demarshal_port_command, - &client_node_demarshal_transport -}; - -static const struct pw_interface pw_protocol_native_client_client_node_interface = { - PIPEWIRE_TYPE_NODE_BASE "Client", - PW_VERSION_CLIENT_NODE, - PW_CLIENT_NODE_METHOD_NUM, &pw_protocol_native_client_client_node_methods, - PW_CLIENT_NODE_EVENT_NUM, pw_protocol_native_client_client_node_demarshal, -}; - static const demarshal_func_t pw_protocol_native_client_module_demarshal[] = { &module_demarshal_info, }; @@ -1025,7 +1034,91 @@ static const struct pw_interface pw_protocol_native_client_link_interface = { PW_LINK_EVENT_NUM, pw_protocol_native_client_link_demarshal, }; -struct pw_protocol *pw_protocol_native_client_init(void) +static const demarshal_func_t pw_protocol_native_server_core_demarshal[PW_CORE_METHOD_NUM] = { + &core_demarshal_update_types_server, + &core_demarshal_sync, + &core_demarshal_get_registry, + &core_demarshal_client_update, + &core_demarshal_create_node, + &core_demarshal_create_link +}; + +static const struct pw_core_events pw_protocol_native_server_core_events = { + &core_marshal_update_types_server, + &core_marshal_done, + &core_marshal_error, + &core_marshal_remove_id, + &core_marshal_info +}; + +const struct pw_interface pw_protocol_native_server_core_interface = { + PIPEWIRE_TYPE__Core, + PW_VERSION_CORE, + PW_CORE_METHOD_NUM, pw_protocol_native_server_core_demarshal, + PW_CORE_EVENT_NUM, &pw_protocol_native_server_core_events, +}; + +static const demarshal_func_t pw_protocol_native_server_registry_demarshal[] = { + ®istry_demarshal_bind, +}; + +static const struct pw_registry_events pw_protocol_native_server_registry_events = { + ®istry_marshal_global, + ®istry_marshal_global_remove, +}; + +const struct pw_interface pw_protocol_native_server_registry_interface = { + PIPEWIRE_TYPE__Registry, + PW_VERSION_REGISTRY, + PW_REGISTRY_METHOD_NUM, pw_protocol_native_server_registry_demarshal, + PW_REGISTRY_EVENT_NUM, &pw_protocol_native_server_registry_events, +}; + +static const struct pw_module_events pw_protocol_native_server_module_events = { + &module_marshal_info, +}; + +const struct pw_interface pw_protocol_native_server_module_interface = { + PIPEWIRE_TYPE__Module, + PW_VERSION_MODULE, + 0, NULL, + PW_MODULE_EVENT_NUM, &pw_protocol_native_server_module_events, +}; + +static const struct pw_node_events pw_protocol_native_server_node_events = { + &node_marshal_info, +}; + +const struct pw_interface pw_protocol_native_server_node_interface = { + PIPEWIRE_TYPE__Node, + PW_VERSION_NODE, + 0, NULL, + PW_NODE_EVENT_NUM, &pw_protocol_native_server_node_events, +}; + +static const struct pw_client_events pw_protocol_native_server_client_events = { + &client_marshal_info, +}; + +const struct pw_interface pw_protocol_native_server_client_interface = { + PIPEWIRE_TYPE__Client, + PW_VERSION_CLIENT, + 0, NULL, + PW_CLIENT_EVENT_NUM, &pw_protocol_native_server_client_events, +}; + +static const struct pw_link_events pw_protocol_native_server_link_events = { + &link_marshal_info, +}; + +const struct pw_interface pw_protocol_native_server_link_interface = { + PIPEWIRE_TYPE__Link, + PW_VERSION_LINK, + 0, NULL, + PW_LINK_EVENT_NUM, &pw_protocol_native_server_link_events, +}; + +struct pw_protocol *pw_protocol_native_init(void) { static bool init = false; struct pw_protocol *protocol; @@ -1037,25 +1130,22 @@ struct pw_protocol *pw_protocol_native_client_init(void) pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_core_interface, - NULL); + &pw_protocol_native_server_core_interface); pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_registry_interface, - NULL); + &pw_protocol_native_server_registry_interface); pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_module_interface, - NULL); + &pw_protocol_native_server_module_interface); pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_node_interface, - NULL); - pw_protocol_add_interfaces(protocol, - &pw_protocol_native_client_client_node_interface, - NULL); + &pw_protocol_native_server_node_interface); pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_client_interface, - NULL); + &pw_protocol_native_server_client_interface); pw_protocol_add_interfaces(protocol, &pw_protocol_native_client_link_interface, - NULL); + &pw_protocol_native_server_link_interface); init = true; diff --git a/pipewire/server/meson.build b/pipewire/server/meson.build index 3e73224e7..f15a3296c 100644 --- a/pipewire/server/meson.build +++ b/pipewire/server/meson.build @@ -9,7 +9,6 @@ pipewirecore_headers = [ 'node.h', 'node-factory.h', 'port.h', - 'protocol-native.h', 'resource.h', 'work-queue.h', ] @@ -25,7 +24,6 @@ pipewirecore_sources = [ 'node.c', 'node-factory.c', 'port.c', - 'protocol-native.c', 'resource.c', 'work-queue.c', ] diff --git a/pipewire/server/protocol-native.h b/pipewire/server/protocol-native.h deleted file mode 100644 index cb50a4f24..000000000 --- a/pipewire/server/protocol-native.h +++ /dev/null @@ -1,22 +0,0 @@ -/* PipeWire - * Copyright (C) 2017 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "pipewire/client/pipewire.h" - -struct pw_protocol *pw_protocol_native_server_init(void);