diff --git a/src/modules/module-protocol-native.c b/src/modules/module-protocol-native.c index fde1ac17e..d3e2775d8 100644 --- a/src/modules/module-protocol-native.c +++ b/src/modules/module-protocol-native.c @@ -581,7 +581,6 @@ on_remote_data(void *data, int fd, uint32_t mask) { struct client *impl = data; struct pw_core_proxy *this = impl->this.core_proxy; - struct pw_remote *remote = pw_proxy_get_remote((struct pw_proxy*)this); struct pw_protocol_native_connection *conn = impl->connection; struct pw_core *core = pw_core_proxy_get_core(this); struct pw_loop *loop = pw_core_get_main_loop(core); @@ -623,7 +622,7 @@ on_remote_data(void *data, int fd, uint32_t mask) pw_log_trace(NAME" %p: got message %d from %u seq:%d", this, msg->opcode, msg->id, msg->seq); - remote->recv_seq = msg->seq; + this->recv_seq = msg->seq; if (debug_messages) { fprintf(stderr, "<<<<<<<<< in: id:%d op:%d size:%d seq:%d\n", @@ -672,7 +671,7 @@ error: pw_log_error(NAME" %p: got connection error %d (%s)", impl, res, spa_strerror(res)); pw_proxy_notify((struct pw_proxy*)this, struct pw_core_proxy_events, error, 0, 0, - remote->recv_seq, res, "connection error"); + this->recv_seq, res, "connection error"); pw_loop_destroy_source(loop, impl->source); impl->source = NULL; pw_core_proxy_disconnect(this); @@ -924,28 +923,28 @@ const static struct pw_protocol_implementaton protocol_impl = { static struct spa_pod_builder * impl_ext_begin_proxy(struct pw_proxy *proxy, uint8_t opcode, struct pw_protocol_native_message **msg) { - struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this); + struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this); return pw_protocol_native_connection_begin(impl->connection, proxy->id, opcode, msg); } static uint32_t impl_ext_add_proxy_fd(struct pw_proxy *proxy, int fd) { - struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this); + struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this); return pw_protocol_native_connection_add_fd(impl->connection, fd); } static int impl_ext_get_proxy_fd(struct pw_proxy *proxy, uint32_t index) { - struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this); + struct client *impl = SPA_CONTAINER_OF(proxy->core_proxy->conn, struct client, this); return pw_protocol_native_connection_get_fd(impl->connection, index); } static int impl_ext_end_proxy(struct pw_proxy *proxy, struct spa_pod_builder *builder) { - struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this); - struct pw_remote *remote = proxy->remote; - return remote->send_seq = pw_protocol_native_connection_end(impl->connection, builder); + struct pw_core_proxy *core_proxy = proxy->core_proxy; + struct client *impl = SPA_CONTAINER_OF(core_proxy->conn, struct client, this); + return core_proxy->send_seq = pw_protocol_native_connection_end(impl->connection, builder); } static struct spa_pod_builder * diff --git a/src/pipewire/core-proxy.c b/src/pipewire/core-proxy.c new file mode 100644 index 000000000..3841be814 --- /dev/null +++ b/src/pipewire/core-proxy.c @@ -0,0 +1,429 @@ +/* PipeWire + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pipewire/pipewire.h" +#include "pipewire/private.h" + +#include "extensions/protocol-native.h" + +#define NAME "core-proxy" + +/** \cond */ + +/** \endcond */ +static void core_event_ping(void *data, uint32_t id, int seq) +{ + struct pw_core_proxy *this = data; + pw_log_debug(NAME" %p: object %u ping %u", this, id, seq); + pw_core_proxy_pong(this->core_proxy, id, seq); +} + +static void core_event_done(void *data, uint32_t id, int seq) +{ + struct pw_core_proxy *this = data; + struct pw_proxy *proxy; + + pw_log_trace(NAME" %p: object %u done %d", this, id, seq); + + proxy = pw_map_lookup(&this->objects, id); + if (proxy) + pw_proxy_emit_done(proxy, seq); +} + +static void core_event_error(void *data, uint32_t id, int seq, int res, const char *message) +{ + struct pw_core_proxy *this = data; + struct pw_proxy *proxy; + + pw_log_error(NAME" %p: object error %u: seq:%d %d (%s): %s", this, id, seq, + res, spa_strerror(res), message); + + proxy = pw_map_lookup(&this->objects, id); + if (proxy) + pw_proxy_emit_error(proxy, seq, res, message); +} + +static void core_event_remove_id(void *data, uint32_t id) +{ + struct pw_core_proxy *this = data; + struct pw_proxy *proxy; + + pw_log_debug(NAME" %p: object remove %u", this, id); + if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) + pw_proxy_remove(proxy); +} + +static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) +{ + struct pw_core_proxy *this = data; + struct pw_proxy *proxy; + + pw_log_debug(NAME" %p: proxy %u bound %u", this, id, global_id); + if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) { + pw_proxy_emit_bound(proxy, global_id); + } +} + +static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags) +{ + struct pw_core_proxy *this = data; + struct pw_memblock *m; + + pw_log_debug(NAME" %p: add mem %u type:%u fd:%d flags:%u", this, id, type, fd, flags); + + m = pw_mempool_import(this->pool, flags, type, fd); + if (m->id != id) { + pw_log_error(NAME" %p: invalid mem id %u, expected %u", + this, id, m->id); + pw_memblock_unref(m); + } +} + +static void core_event_remove_mem(void *data, uint32_t id) +{ + struct pw_core_proxy *this = data; + pw_log_debug(NAME" %p: remove mem %u", this, id); + pw_mempool_unref_id(this->pool, id); +} + +static const struct pw_core_proxy_events core_events = { + PW_VERSION_CORE_PROXY_EVENTS, + .error = core_event_error, + .ping = core_event_ping, + .done = core_event_done, + .remove_id = core_event_remove_id, + .bound_id = core_event_bound_id, + .add_mem = core_event_add_mem, + .remove_mem = core_event_remove_mem, +}; + +SPA_EXPORT +struct pw_core *pw_core_proxy_get_core(struct pw_core_proxy *core_proxy) +{ + return core_proxy->core; +} + +SPA_EXPORT +const struct pw_properties *pw_core_proxy_get_properties(struct pw_core_proxy *core_proxy) +{ + return core_proxy->properties; +} + +SPA_EXPORT +int pw_core_proxy_update_properties(struct pw_core_proxy *core_proxy, const struct spa_dict *dict) +{ + int changed; + + changed = pw_properties_update(core_proxy->properties, dict); + + pw_log_debug(NAME" %p: updated %d properties", core_proxy, changed); + + if (!changed) + return 0; + + if (core_proxy->client_proxy) + pw_client_proxy_update_properties(core_proxy->client_proxy, &core_proxy->properties->dict); + + return changed; +} + +SPA_EXPORT +void *pw_core_proxy_get_user_data(struct pw_core_proxy *core_proxy) +{ + return core_proxy->user_data; +} + +static int destroy_proxy(void *object, void *data) +{ + struct pw_core_proxy *core_proxy = data; + + if (object && object != core_proxy) + pw_proxy_destroy(object); + + return 0; +} + +static void core_proxy_destroy(void *data) +{ + struct pw_core_proxy *core_proxy = data; + struct pw_stream *stream, *s2; + struct pw_filter *filter; + + pw_log_debug(NAME" %p: core proxy destroy", core_proxy); + + spa_list_for_each_safe(stream, s2, &core_proxy->stream_list, link) + pw_stream_disconnect(stream); + + pw_protocol_client_disconnect(core_proxy->conn); + + core_proxy->client_proxy = NULL; + + pw_map_for_each(&core_proxy->objects, destroy_proxy, core_proxy); + pw_map_reset(&core_proxy->objects); + + pw_mempool_destroy(core_proxy->pool); + + spa_list_consume(stream, &core_proxy->stream_list, link) + pw_stream_destroy(stream); + spa_list_consume(filter, &core_proxy->filter_list, link) + pw_filter_destroy(filter); + + pw_protocol_client_destroy(core_proxy->conn); + + spa_list_remove(&core_proxy->link); + + pw_map_clear(&core_proxy->objects); + + pw_log_debug(NAME" %p: free", core_proxy); + pw_properties_free(core_proxy->properties); +} + +static const struct pw_proxy_events core_proxy_events = { + PW_VERSION_PROXY_EVENTS, + .destroy = core_proxy_destroy, +}; + +SPA_EXPORT +struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *core_proxy) +{ + return core_proxy->client_proxy; +} + +SPA_EXPORT +struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *core_proxy, uint32_t id) +{ + return pw_map_lookup(&core_proxy->objects, id); +} + +SPA_EXPORT +struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *core_proxy, + uint32_t type, struct pw_properties *props, void *object, + size_t user_data_size) +{ + struct pw_proxy *proxy; + const struct pw_export_type *t; + int res; + + t = pw_core_find_export_type(core_proxy->core, type); + if (t == NULL) { + res = -EPROTO; + goto error_export_type; + } + + proxy = t->func(core_proxy, type, props, object, user_data_size); + if (proxy == NULL) { + res = -errno; + goto error_proxy_failed; + } + return proxy; + +error_export_type: + pw_log_error(NAME" %p: can't export type %d: %s", core_proxy, type, spa_strerror(res)); + goto exit_free; +error_proxy_failed: + pw_log_error(NAME" %p: failed to create proxy: %s", core_proxy, spa_strerror(res)); + goto exit; +exit_free: + if (props) + pw_properties_free(props); +exit: + errno = -res; + return NULL; +} + +static struct pw_core_proxy *core_proxy_new(struct pw_core *core, + struct pw_properties *properties, size_t user_data_size) +{ + struct pw_core_proxy *p; + struct pw_protocol *protocol = NULL; + const char *protocol_name; + int res; + + p = calloc(1, sizeof(struct pw_core_proxy) + user_data_size); + if (p == NULL) { + res = -errno; + goto exit_cleanup; + } + + if (properties == NULL) + properties = pw_properties_new(NULL, NULL); + if (properties == NULL) + goto error_properties; + + p->proxy.core_proxy = p; + p->core = core; + p->properties = properties; + p->pool = pw_mempool_new(NULL); + p->core_proxy = p; + if (user_data_size > 0) + p->user_data = SPA_MEMBER(p, sizeof(struct pw_core_proxy), void); + p->proxy.user_data = p->user_data; + + pw_map_init(&p->objects, 64, 32); + spa_list_init(&p->stream_list); + spa_list_init(&p->filter_list); + + if ((protocol_name = pw_properties_get(properties, PW_KEY_PROTOCOL)) == NULL) { + if ((protocol_name = pw_properties_get(core->properties, PW_KEY_PROTOCOL)) == NULL) { + protocol_name = PW_TYPE_INFO_PROTOCOL_Native; + if ((protocol = pw_core_find_protocol(core, protocol_name)) == NULL) { + res = -ENOTSUP; + goto error_protocol; + } + } + } + + if (protocol == NULL) + protocol = pw_core_find_protocol(core, protocol_name); + if (protocol == NULL) { + res = -ENOTSUP; + goto error_protocol; + } + + p->conn = pw_protocol_new_client(protocol, properties); + if (p->conn == NULL) + goto error_connection; + + p->conn->core_proxy = p; + + if ((res = pw_proxy_init(&p->proxy, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE_PROXY)) < 0) + goto error_proxy; + + p->client_proxy = (struct pw_client_proxy*)pw_proxy_new(&p->proxy, + PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT_PROXY, 0); + if (p->client_proxy == NULL) { + res = -errno; + goto error_proxy; + } + + pw_core_proxy_add_listener(p, &p->core_listener, &core_events, p); + pw_proxy_add_listener(&p->proxy, &p->core_proxy_listener, &core_proxy_events, p); + + pw_core_proxy_hello(p, PW_VERSION_CORE_PROXY); + pw_client_proxy_update_properties(p->client_proxy, &p->properties->dict); + + spa_list_append(&core->core_proxy_list, &p->link); + + return p; + +error_properties: + res = -errno; + pw_log_error(NAME" %p: can't create properties: %m", p); + goto exit_free; +error_protocol: + pw_log_error(NAME" %p: can't find native protocol: %s", p, spa_strerror(res)); + goto exit_free; +error_connection: + res = -errno; + pw_log_error(NAME" %p: can't create new native protocol connection: %m", p); + goto exit_free; +error_proxy: + pw_log_error(NAME" %p: can't initialize proxy: %s", p, spa_strerror(res)); + goto exit_free; + +exit_free: + free(p); +exit_cleanup: + if (properties) + pw_properties_free(properties); + errno = -res; + return NULL; +} + +SPA_EXPORT +struct pw_core_proxy * +pw_core_connect(struct pw_core *core, struct pw_properties *properties, + size_t user_data_size) +{ + struct pw_core_proxy *core_proxy; + int res; + + core_proxy = core_proxy_new(core, properties, user_data_size); + if (core_proxy == NULL) + return NULL; + + if ((res = pw_protocol_client_connect(core_proxy->conn, + &core_proxy->properties->dict, + NULL, NULL)) < 0) + goto error_free; + + return core_proxy; + +error_free: + pw_core_proxy_disconnect(core_proxy); + errno = -res; + return NULL; +} + +SPA_EXPORT +struct pw_core_proxy * +pw_core_connect_fd(struct pw_core *core, int fd, struct pw_properties *properties, + size_t user_data_size) +{ + struct pw_core_proxy *core_proxy; + int res; + + core_proxy = core_proxy_new(core, properties, user_data_size); + if (core_proxy == NULL) + return NULL; + + if ((res = pw_protocol_client_connect_fd(core_proxy->conn, fd, true)) < 0) + goto error_free; + + return core_proxy; + +error_free: + pw_core_proxy_disconnect(core_proxy); + errno = -res; + return NULL; +} + +SPA_EXPORT +int pw_core_proxy_steal_fd(struct pw_core_proxy *proxy) +{ + return pw_protocol_client_steal_fd(proxy->conn); +} + +SPA_EXPORT +struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy) +{ + return proxy->pool; +} + +SPA_EXPORT +int pw_core_proxy_disconnect(struct pw_core_proxy *proxy) +{ + pw_proxy_destroy(&proxy->proxy); + return 0; +} diff --git a/src/pipewire/core-proxy.h b/src/pipewire/core-proxy.h new file mode 100644 index 000000000..2083237ca --- /dev/null +++ b/src/pipewire/core-proxy.h @@ -0,0 +1,86 @@ +/* PipeWire + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef PIPEWIRE_REMOTE_H +#define PIPEWIRE_REMOTE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include +#include + +/** Connect to a PipeWire instance \memberof pw_core_proxy + * \return a pw_core_proxy on success or NULL with errno set on error */ +struct pw_core_proxy * +pw_core_connect(struct pw_core *core, /**< a \ref pw_core */ + struct pw_properties *properties, /**< optional properties, ownership of + * the properties is taken.*/ + size_t user_data_size /**< extra user data size */); + +/** Connect to a PipeWire instance on the given socket \memberof pw_core_proxy + * \param fd the connected socket to use, the socket will be closed + * automatically on disconnect or error. + * \return a pw_core_proxy on success or NULL with errno set on error */ +struct pw_core_proxy * +pw_core_connect_fd(struct pw_core *core, /**< a \ref pw_core */ + int fd, /**< an fd */ + struct pw_properties *properties, /**< optional properties, ownership of + * the properties is taken.*/ + size_t user_data_size /**< extra user data size */); + +/** Steal the fd of the core_proxy connection or < 0 on error. The core_proxy + * will be disconnected after this call. */ +int pw_core_proxy_steal_fd(struct pw_core_proxy *core_proxy); + +/** Get the core proxy, can only be called when connected */ +int pw_core_proxy_disconnect(struct pw_core_proxy *proxy); + +/** Get the client proxy */ +struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy); + +struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy); + +struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy); + +/** Get the proxy with the given id */ +struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id); + +struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, /**< the proxy */ + uint32_t type, /**< the type of object */ + struct pw_properties *properties, /**< extra properties */ + void *object, /**< object to export */ + size_t user_data_size /**< extra user data */); + + +#ifdef __cplusplus +} +#endif + +#endif /* PIPEWIRE_REMOTE_H */ diff --git a/src/pipewire/core.c b/src/pipewire/core.c index e7e6b9ed8..f85fdbfd8 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -570,7 +570,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, pw_map_init(&this->globals, 128, 32); spa_list_init(&this->protocol_list); - spa_list_init(&this->remote_list); + spa_list_init(&this->core_proxy_list); spa_list_init(&this->registry_resource_list); spa_list_init(&this->global_list); spa_list_init(&this->module_list); @@ -660,7 +660,7 @@ void pw_core_destroy(struct pw_core *core) struct pw_global *global; struct pw_module *module; struct pw_device *device; - struct pw_remote *remote; + struct pw_core_proxy *core_proxy; struct pw_resource *resource; struct pw_node *node; struct factory_entry *entry; @@ -670,8 +670,8 @@ void pw_core_destroy(struct pw_core *core) spa_hook_remove(&core->global_listener); - spa_list_consume(remote, &core->remote_list, link) - pw_remote_destroy(remote); + spa_list_consume(core_proxy, &core->core_proxy_list, link) + pw_core_proxy_disconnect(core_proxy); spa_list_consume(module, &core->module_list, link) pw_module_destroy(module); diff --git a/src/pipewire/core.h b/src/pipewire/core.h index 7291b6dbe..406dc1c2d 100644 --- a/src/pipewire/core.h +++ b/src/pipewire/core.h @@ -45,7 +45,7 @@ struct pw_core; #include #include #include -#include +#include #include #include #include diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 63b7229dd..d955eb206 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -947,8 +947,6 @@ filter_new(struct pw_core *core, const char *name, impl->core = core; -// spa_list_append(&remote->filter_list, &this->link); - return impl; error_properties: @@ -1048,7 +1046,6 @@ void pw_filter_destroy(struct pw_filter *filter) spa_hook_remove(&filter->core_listener); filter->core_proxy = NULL; } -// spa_list_remove(&filter->link); clear_params(impl, NULL, SPA_ID_INVALID); diff --git a/src/pipewire/filter.h b/src/pipewire/filter.h index 96978019f..d5df1780f 100644 --- a/src/pipewire/filter.h +++ b/src/pipewire/filter.h @@ -44,7 +44,7 @@ struct pw_filter; #include #include -#include +#include /** \enum pw_filter_state The state of a filter \memberof pw_filter */ enum pw_filter_state { diff --git a/src/pipewire/introspect.c b/src/pipewire/introspect.c index d8f6442b2..8108fbbec 100644 --- a/src/pipewire/introspect.c +++ b/src/pipewire/introspect.c @@ -28,7 +28,7 @@ #include "pipewire/pipewire.h" -#include "pipewire/remote.h" +#include "pipewire/core-proxy.h" SPA_EXPORT const char *pw_node_state_as_string(enum pw_node_state state) diff --git a/src/pipewire/meson.build b/src/pipewire/meson.build index 357531b25..67f4ce8b6 100644 --- a/src/pipewire/meson.build +++ b/src/pipewire/meson.build @@ -26,7 +26,7 @@ pipewire_headers = [ 'properties.h', 'protocol.h', 'proxy.h', - 'remote.h', + 'core-proxy.h', 'resource.h', 'stream.h', 'thread-loop.h', @@ -58,7 +58,7 @@ pipewire_sources = [ 'properties.c', 'protocol.c', 'proxy.c', - 'remote.c', + 'core-proxy.c', 'resource.c', 'stream.c', 'thread-loop.c', diff --git a/src/pipewire/pipewire.h b/src/pipewire/pipewire.h index 3a0a14411..90aa69860 100644 --- a/src/pipewire/pipewire.h +++ b/src/pipewire/pipewire.h @@ -47,7 +47,7 @@ extern "C" { #include #include #include -#include +#include #include #include #include diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 1ae324631..ea6493718 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -34,7 +34,6 @@ extern "C" { #include "pipewire/buffers.h" #include "pipewire/map.h" -#include "pipewire/remote.h" #include "pipewire/mem.h" #include "pipewire/introspect.h" #include "pipewire/interfaces.h" @@ -222,7 +221,7 @@ struct pw_core { struct pw_map globals; /**< map of globals */ struct spa_list protocol_list; /**< list of protocols */ - struct spa_list remote_list; /**< list of remote connections */ + struct spa_list core_proxy_list; /**< list of remote connections */ struct spa_list registry_resource_list; /**< list of registry resources */ struct spa_list module_list; /**< list of modules */ struct spa_list device_list; /**< list of devices */ @@ -713,7 +712,7 @@ struct pw_resource { struct pw_proxy { struct spa_interface impl; /**< object implementation */ - struct pw_remote *remote; /**< the owner remote of this proxy */ + struct pw_core_proxy *core_proxy; /**< the owner core_proxy of this proxy */ uint32_t id; /**< client side id */ uint32_t type; /**< type of the interface */ @@ -731,17 +730,18 @@ struct pw_proxy { void *user_data; /**< extra user data */ }; -#define pw_remote_emit(r,m,v,...) spa_hook_list_call(&r->listener_list, struct pw_remote_events, m, v, ##__VA_ARGS__) -#define pw_remote_emit_destroy(r) pw_remote_emit(r, destroy, 0) -#define pw_remote_emit_state_changed(r,o,s,e) pw_remote_emit(r, state_changed, 0, o, s, e) +struct pw_core_proxy { + struct pw_proxy proxy; -struct pw_remote { struct pw_core *core; /**< core */ - struct spa_list link; /**< link in core remote_list */ + struct spa_list link; /**< link in core core_proxy_list */ struct pw_properties *properties; /**< extra properties */ struct pw_mempool *pool; /**< memory pool */ struct pw_core_proxy *core_proxy; /**< proxy for the core object */ + struct spa_hook core_listener; + struct spa_hook core_proxy_listener; + struct pw_map objects; /**< map of client side proxy objects * indexed with the client id */ struct pw_client_proxy *client_proxy; /**< proxy for the client object */ @@ -899,6 +899,8 @@ pw_core_find_port(struct pw_core *core, const struct pw_export_type *pw_core_find_export_type(struct pw_core *core, uint32_t type); +int pw_proxy_init(struct pw_proxy *proxy, uint32_t type, uint32_t version); + int pw_proxy_install_marshal(struct pw_proxy *proxy, bool implementor); void pw_proxy_remove(struct pw_proxy *proxy); diff --git a/src/pipewire/proxy.c b/src/pipewire/proxy.c index 79a734eb1..86e2f3b3c 100644 --- a/src/pipewire/proxy.c +++ b/src/pipewire/proxy.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -40,6 +39,38 @@ struct proxy { }; /** \endcond */ +int pw_proxy_init(struct pw_proxy *proxy, uint32_t type, uint32_t version) +{ + int res; + + proxy->refcount = 1; + proxy->type = type; + proxy->version = version; + + proxy->id = pw_map_insert_new(&proxy->core_proxy->objects, proxy); + if (proxy->id == SPA_ID_INVALID) { + res = -errno; + pw_log_error(NAME" %p: can't allocate new id: %m", proxy); + goto error; + } + + spa_hook_list_init(&proxy->listener_list); + spa_hook_list_init(&proxy->object_listener_list); + + if ((res = pw_proxy_install_marshal(proxy, false)) < 0) { + pw_log_error(NAME" %p: no marshal for type %s/%d", proxy, + spa_debug_type_find_name(pw_type_info(), type), + version); + goto error_clean; + } + return 0; + +error_clean: + pw_map_remove(&proxy->core_proxy->objects, proxy->id); +error: + return res; +} + /** Create a proxy object with a given id and type * * \param factory another proxy object that serves as a factory @@ -50,7 +81,7 @@ struct proxy { * This function creates a new proxy object with the supplied id and type. The * proxy object will have an id assigned from the client id space. * - * \sa pw_remote + * \sa pw_core_proxy * * \memberof pw_proxy */ @@ -61,7 +92,6 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory, { struct proxy *impl; struct pw_proxy *this; - struct pw_remote *remote = factory->remote; int res; impl = calloc(1, sizeof(struct proxy) + user_data_size); @@ -69,38 +99,21 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory, return NULL; this = &impl->this; - this->remote = remote; - this->refcount = 1; - this->type = type; - this->version = version; + this->core_proxy = factory->core_proxy; - this->id = pw_map_insert_new(&remote->objects, this); - if (this->id == SPA_ID_INVALID) { - res = -errno; - pw_log_error(NAME" %p: can't allocate new id: %m", this); - goto error_clean; - } - - spa_hook_list_init(&this->listener_list); - spa_hook_list_init(&this->object_listener_list); - - if ((res = pw_proxy_install_marshal(this, false)) < 0) { - pw_log_error(NAME" %p: no marshal for type %s/%d", this, - spa_debug_type_find_name(pw_type_info(), type), - version); - goto error_clean; - } + if ((res = pw_proxy_init(this, type, version)) < 0) + goto error_init; if (user_data_size > 0) this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void); - pw_log_debug(NAME" %p: new %u type %s/%d remote:%p, marshal:%p", + pw_log_debug(NAME" %p: new %u type %s/%d core-proxy:%p, marshal:%p", this, this->id, spa_debug_type_find_name(pw_type_info(), type), version, - remote, this->marshal); + this->core_proxy, this->marshal); return this; -error_clean: +error_init: free(impl); errno = -res; return NULL; @@ -109,10 +122,10 @@ error_clean: SPA_EXPORT int pw_proxy_install_marshal(struct pw_proxy *this, bool implementor) { - struct pw_remote *remote = this->remote; + struct pw_core_proxy *core_proxy = this->core_proxy; const struct pw_protocol_marshal *marshal; - marshal = pw_protocol_get_marshal(remote->conn->protocol, + marshal = pw_protocol_get_marshal(core_proxy->conn->protocol, this->type, this->version, implementor ? PW_PROTOCOL_MARSHAL_FLAG_IMPL : 0); if (marshal == NULL) @@ -147,15 +160,15 @@ uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version) } SPA_EXPORT -struct pw_remote *pw_proxy_get_remote(struct pw_proxy *proxy) +struct pw_core_proxy *pw_proxy_get_core_proxy(struct pw_proxy *proxy) { - return proxy->remote; + return proxy->core_proxy; } SPA_EXPORT struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy) { - return proxy->remote->conn->protocol; + return proxy->core_proxy->conn->protocol; } SPA_EXPORT @@ -180,14 +193,14 @@ void pw_proxy_add_object_listener(struct pw_proxy *proxy, * * \param proxy Proxy object to destroy * - * \note This is normally called by \ref pw_remote when the server + * \note This is normally called by \ref pw_core_proxy when the server * decides to destroy the server side object * \memberof pw_proxy */ SPA_EXPORT void pw_proxy_destroy(struct pw_proxy *proxy) { - struct pw_remote *remote = proxy->remote; + struct pw_core_proxy *core_proxy = proxy->core_proxy; if (!proxy->zombie) { pw_log_debug(NAME" %p: destroy %u", proxy, proxy->id); @@ -196,15 +209,15 @@ void pw_proxy_destroy(struct pw_proxy *proxy) if (!proxy->removed) { /* if the server did not remove this proxy, remove ourselves * from the proxy objects and schedule a destroy. */ - if (remote->core_proxy) { + if (core_proxy) { proxy->zombie = true; - pw_core_proxy_destroy(remote->core_proxy, proxy); + pw_core_proxy_destroy(core_proxy, proxy); } else { proxy->removed = true; } } if (proxy->removed) { - pw_map_remove(&remote->objects, proxy->id); + pw_map_remove(&core_proxy->objects, proxy->id); pw_proxy_unref(proxy); } @@ -230,10 +243,10 @@ SPA_EXPORT int pw_proxy_sync(struct pw_proxy *proxy, int seq) { int res = -EIO; - struct pw_remote *remote = proxy->remote; + struct pw_core_proxy *core_proxy = proxy->core_proxy; - if (remote->core_proxy != NULL) { - res = pw_core_proxy_sync(remote->core_proxy, proxy->id, seq); + if (core_proxy != NULL) { + res = pw_core_proxy_sync(core_proxy, proxy->id, seq); pw_log_debug(NAME" %p: %u seq:%d sync %u", proxy, proxy->id, seq, res); } return res; @@ -244,12 +257,12 @@ int pw_proxy_errorf(struct pw_proxy *proxy, int res, const char *error, ...) { va_list ap; int r = -EIO; - struct pw_remote *remote = proxy->remote; + struct pw_core_proxy *core_proxy = proxy->core_proxy; va_start(ap, error); - if (remote->core_proxy != NULL) - r = pw_core_proxy_errorv(remote->core_proxy, proxy->id, - remote->recv_seq, res, error, ap); + if (core_proxy != NULL) + r = pw_core_proxy_errorv(core_proxy, proxy->id, + core_proxy->recv_seq, res, error, ap); va_end(ap); return r; } @@ -258,10 +271,10 @@ SPA_EXPORT int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error) { int r = -EIO; - struct pw_remote *remote = proxy->remote; - if (remote->core_proxy != NULL) - r = pw_core_proxy_error(remote->core_proxy, proxy->id, - remote->recv_seq, res, error); + struct pw_core_proxy *core_proxy = proxy->core_proxy; + if (core_proxy != NULL) + r = pw_core_proxy_error(core_proxy, proxy->id, + core_proxy->recv_seq, res, error); return r; } diff --git a/src/pipewire/proxy.h b/src/pipewire/proxy.h index d32ec7374..d9e92f4d8 100644 --- a/src/pipewire/proxy.h +++ b/src/pipewire/proxy.h @@ -43,9 +43,8 @@ extern "C" { * \section sec_page_proxy_core Core proxy * * A proxy for a remote core object can be obtained by making - * a remote connection. See \ref pw_page_remote_api - * - * A pw_core_proxy can then be retrieved with \ref pw_remote_get_core_proxy + * a remote connection with \ref pw_core_connect. + * See \ref pw_page_remote_api * * Some methods on proxy object allow creation of more proxy objects or * create a binding between a local proxy and global resource. @@ -154,9 +153,6 @@ uint32_t pw_proxy_get_id(struct pw_proxy *proxy); /** Get the type and version of the proxy */ uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version); -/** Get the remote managing this proxy */ -struct pw_remote *pw_proxy_get_remote(struct pw_proxy *proxy); - /** Get the protocol used for the proxy */ struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy); diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c deleted file mode 100644 index db025cfc5..000000000 --- a/src/pipewire/remote.c +++ /dev/null @@ -1,572 +0,0 @@ -/* PipeWire - * - * Copyright © 2018 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pipewire/pipewire.h" -#include "pipewire/private.h" - -#include "extensions/protocol-native.h" - -#define NAME "remote" - -/** \cond */ - -struct remote { - struct pw_remote this; - struct spa_hook core_listener; - struct spa_hook core_proxy_listener; - size_t user_data_size; -}; - -/** \endcond */ -static void core_event_ping(void *data, uint32_t id, int seq) -{ - struct pw_remote *this = data; - pw_log_debug(NAME" %p: object %u ping %u", this, id, seq); - pw_core_proxy_pong(this->core_proxy, id, seq); -} - -static void core_event_done(void *data, uint32_t id, int seq) -{ - struct pw_remote *this = data; - struct pw_proxy *proxy; - - pw_log_trace(NAME" %p: object %u done %d", this, id, seq); - - proxy = pw_map_lookup(&this->objects, id); - if (proxy) - pw_proxy_emit_done(proxy, seq); -} - -static void core_event_error(void *data, uint32_t id, int seq, int res, const char *message) -{ - struct pw_remote *this = data; - struct pw_proxy *proxy; - - pw_log_error(NAME" %p: object error %u: seq:%d %d (%s): %s", this, id, seq, - res, spa_strerror(res), message); - - proxy = pw_map_lookup(&this->objects, id); - if (proxy) - pw_proxy_emit_error(proxy, seq, res, message); -} - -static void core_event_remove_id(void *data, uint32_t id) -{ - struct pw_remote *this = data; - struct pw_proxy *proxy; - - pw_log_debug(NAME" %p: object remove %u", this, id); - if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) - pw_proxy_remove(proxy); -} - -static void core_event_bound_id(void *data, uint32_t id, uint32_t global_id) -{ - struct pw_remote *this = data; - struct pw_proxy *proxy; - - pw_log_debug(NAME" %p: proxy %u bound %u", this, id, global_id); - if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) { - pw_proxy_emit_bound(proxy, global_id); - } -} - -static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, uint32_t flags) -{ - struct pw_remote *this = data; - struct pw_memblock *m; - - pw_log_debug(NAME" %p: add mem %u type:%u fd:%d flags:%u", this, id, type, fd, flags); - - m = pw_mempool_import(this->pool, flags, type, fd); - if (m->id != id) { - pw_log_error(NAME" %p: invalid mem id %u, expected %u", - this, id, m->id); - pw_memblock_unref(m); - } -} - -static void core_event_remove_mem(void *data, uint32_t id) -{ - struct pw_remote *this = data; - pw_log_debug(NAME" %p: remove mem %u", this, id); - pw_mempool_unref_id(this->pool, id); -} - -static const struct pw_core_proxy_events core_events = { - PW_VERSION_CORE_PROXY_EVENTS, - .error = core_event_error, - .ping = core_event_ping, - .done = core_event_done, - .remove_id = core_event_remove_id, - .bound_id = core_event_bound_id, - .add_mem = core_event_add_mem, - .remove_mem = core_event_remove_mem, -}; - -SPA_EXPORT -struct pw_remote *pw_remote_new(struct pw_core *core, - struct pw_properties *properties, - size_t user_data_size) -{ - struct remote *impl; - struct pw_remote *this; - struct pw_protocol *protocol = NULL; - const char *protocol_name; - int res; - - impl = calloc(1, sizeof(struct remote) + user_data_size); - if (impl == NULL) { - res = -errno; - goto exit_cleanup; - } - - this = &impl->this; - pw_log_debug(NAME" %p: new", impl); - - this->core = core; - impl->user_data_size = user_data_size; - - if (user_data_size > 0) - this->user_data = SPA_MEMBER(impl, sizeof(struct remote), void); - - if (properties == NULL) - properties = pw_properties_new(NULL, NULL); - if (properties == NULL) - goto error_properties; - - pw_fill_remote_properties(core, properties); - this->properties = properties; - - pw_map_init(&this->objects, 64, 32); - - spa_list_init(&this->stream_list); - spa_list_init(&this->filter_list); - - if ((protocol_name = pw_properties_get(properties, PW_KEY_PROTOCOL)) == NULL) { - if ((protocol_name = pw_properties_get(core->properties, PW_KEY_PROTOCOL)) == NULL) { - protocol_name = PW_TYPE_INFO_PROTOCOL_Native; - if ((protocol = pw_core_find_protocol(core, protocol_name)) == NULL) { - goto error_protocol; - } - } - } - - if (protocol == NULL) - protocol = pw_core_find_protocol(core, protocol_name); - if (protocol == NULL) { - res = -ENOTSUP; - goto error_protocol; - } - - this->conn = pw_protocol_new_client(protocol, properties); - if (this->conn == NULL) - goto error_connection; - - spa_list_append(&core->remote_list, &this->link); - - return this; - -error_properties: - res = -errno; - pw_log_error(NAME" %p: can't create properties: %m", this); - goto exit_free; -error_protocol: - pw_log_error(NAME" %p: can't load native protocol: %s", this, spa_strerror(res)); - goto exit_free; -error_connection: - res = -errno; - pw_log_error(NAME" %p: can't create new native protocol connection: %m", this); - goto exit_free; - -exit_free: - free(impl); -exit_cleanup: - if (properties) - pw_properties_free(properties); - errno = -res; - return NULL; -} - -SPA_EXPORT -void pw_remote_destroy(struct pw_remote *remote) -{ - struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this); - struct pw_stream *stream; - struct pw_filter *filter; - - pw_log_debug(NAME" %p: destroy", remote); - - pw_remote_disconnect(remote); - - spa_list_consume(stream, &remote->stream_list, link) - pw_stream_destroy(stream); - spa_list_consume(filter, &remote->filter_list, link) - pw_filter_destroy(filter); - - pw_protocol_client_destroy(remote->conn); - - spa_list_remove(&remote->link); - - pw_map_clear(&remote->objects); - - pw_log_debug(NAME" %p: free", remote); - pw_properties_free(remote->properties); - free(impl); -} - -SPA_EXPORT -struct pw_core *pw_remote_get_core(struct pw_remote *remote) -{ - return remote->core; -} - -SPA_EXPORT -const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote) -{ - return remote->properties; -} - -SPA_EXPORT -int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict) -{ - int changed; - - changed = pw_properties_update(remote->properties, dict); - - pw_log_debug(NAME" %p: updated %d properties", remote, changed); - - if (!changed) - return 0; - - if (remote->client_proxy) - pw_client_proxy_update_properties(remote->client_proxy, &remote->properties->dict); - - return changed; -} - -SPA_EXPORT -void *pw_remote_get_user_data(struct pw_remote *remote) -{ - return remote->user_data; -} - -static void core_proxy_destroy(void *data) -{ - struct pw_remote *remote = data; - struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this); - - pw_log_debug(NAME" %p: core proxy destroy", remote); - if (remote->core_proxy) { - spa_hook_remove(&impl->core_proxy_listener); - spa_hook_remove(&impl->core_listener); - remote->core_proxy = NULL; - } -} - - -static const struct pw_proxy_events core_proxy_events = { - PW_VERSION_PROXY_EVENTS, - .destroy = core_proxy_destroy, -}; - -static int init_connect(struct pw_remote *remote) -{ - struct remote *impl = SPA_CONTAINER_OF(remote, struct remote, this); - struct pw_proxy dummy, *core_proxy; - int res; - - spa_zero(dummy); - dummy.remote = remote; - - core_proxy = pw_proxy_new(&dummy, - PW_TYPE_INTERFACE_Core, - PW_VERSION_CORE_PROXY, - impl->user_data_size); - if (core_proxy == NULL) { - res = -errno; - goto error; - } - remote->core_proxy = (struct pw_core_proxy*)core_proxy; - - remote->client_proxy = (struct pw_client_proxy*)pw_proxy_new(&dummy, - PW_TYPE_INTERFACE_Client, PW_VERSION_CLIENT_PROXY, 0); - if (remote->client_proxy == NULL) { - res = -errno; - goto error_clean_core_proxy; - } - remote->pool = pw_mempool_new(NULL); - - pw_core_proxy_add_listener(remote->core_proxy, &impl->core_listener, &core_events, remote); - pw_proxy_add_listener(core_proxy, &impl->core_proxy_listener, &core_proxy_events, remote); - - pw_core_proxy_hello(remote->core_proxy, PW_VERSION_CORE_PROXY); - pw_client_proxy_update_properties(remote->client_proxy, &remote->properties->dict); - - remote->conn->core_proxy = remote->core_proxy; - - return 0; - -error_clean_core_proxy: - pw_proxy_remove((struct pw_proxy*)remote->core_proxy); -error: - return res; -} - -SPA_EXPORT -struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote) -{ - return remote->core_proxy; -} - -SPA_EXPORT -struct pw_client_proxy * pw_remote_get_client_proxy(struct pw_remote *remote) -{ - return remote->client_proxy; -} - -SPA_EXPORT -struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id) -{ - return pw_map_lookup(&remote->objects, id); -} - -SPA_EXPORT -int pw_remote_connect(struct pw_remote *remote) -{ - int res; - - if ((res = init_connect(remote)) < 0) - goto error; - - if ((res = pw_protocol_client_connect(remote->conn, - &remote->properties->dict, - NULL, NULL)) < 0) - goto error; - -error: - return res; -} - -SPA_EXPORT -int pw_remote_connect_fd(struct pw_remote *remote, int fd) -{ - int res; - - if ((res = init_connect(remote)) < 0) - goto error; - - if ((res = pw_protocol_client_connect_fd(remote->conn, fd, true)) < 0) - goto error; - -error: - return res; -} - -SPA_EXPORT -int pw_remote_steal_fd(struct pw_remote *remote) -{ - int fd; - fd = pw_protocol_client_steal_fd(remote->conn); - return fd; -} - -static int destroy_proxy(void *object, void *data) -{ - if (object) - pw_proxy_destroy(object); - return 0; -} - -SPA_EXPORT -int pw_remote_disconnect(struct pw_remote *remote) -{ - struct pw_stream *stream, *s2; - - pw_log_debug(NAME" %p: disconnect", remote); - - spa_list_for_each_safe(stream, s2, &remote->stream_list, link) - pw_stream_disconnect(stream); - - pw_protocol_client_disconnect(remote->conn); - - remote->client_proxy = NULL; - - pw_map_for_each(&remote->objects, destroy_proxy, remote); - pw_map_reset(&remote->objects); - - pw_mempool_destroy(remote->pool); - - return 0; -} - -SPA_EXPORT -struct pw_proxy *pw_remote_export(struct pw_remote *remote, - uint32_t type, struct pw_properties *props, void *object, - size_t user_data_size) -{ - struct pw_proxy *proxy; - const struct pw_export_type *t; - int res; - - if (remote->core_proxy == NULL) { - res = -ENETDOWN; - goto error_core_proxy; - } - - t = pw_core_find_export_type(remote->core, type); - if (t == NULL) { - res = -EPROTO; - goto error_export_type; - } - - proxy = t->func(remote->core_proxy, type, props, object, user_data_size); - if (proxy == NULL) { - res = -errno; - goto error_proxy_failed; - } - return proxy; - -error_core_proxy: - pw_log_error(NAME" %p: no core proxy: %s", remote, spa_strerror(res)); - goto exit_free; -error_export_type: - pw_log_error(NAME" %p: can't export type %d: %s", remote, type, spa_strerror(res)); - goto exit_free; -error_proxy_failed: - pw_log_error(NAME" %p: failed to create proxy: %s", remote, spa_strerror(res)); - goto exit; -exit_free: - if (props) - pw_properties_free(props); -exit: - errno = -res; - return NULL; -} - -SPA_EXPORT -struct pw_core_proxy * -pw_core_connect(struct pw_core *core, struct pw_properties *properties, - size_t user_data_size) -{ - struct pw_remote *remote; - int res; - - remote = pw_remote_new(core, properties, user_data_size); - if (remote == NULL) - return NULL; - - if ((res = pw_remote_connect(remote)) < 0) - goto error_free; - - return remote->core_proxy; - -error_free: - pw_remote_destroy(remote); - errno = -res; - return NULL; -} - -SPA_EXPORT -struct pw_core_proxy * -pw_core_connect_fd(struct pw_core *core, int fd, struct pw_properties *properties, - size_t user_data_size) -{ - struct pw_remote *remote; - int res; - - remote = pw_remote_new(core, properties, user_data_size); - if (remote == NULL) - return NULL; - - if ((res = pw_remote_connect_fd(remote, fd)) < 0) - goto error_free; - - return remote->core_proxy; - -error_free: - pw_remote_destroy(remote); - errno = -res; - return NULL; -} - -SPA_EXPORT -struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - return remote->client_proxy; -} - -SPA_EXPORT -struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - return remote->core; -} -SPA_EXPORT -struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy) -{ - return ((struct pw_proxy*)proxy)->remote; -} - -SPA_EXPORT -struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - return remote->pool; -} - -SPA_EXPORT -struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - return pw_remote_find_proxy(remote, id); -} - -SPA_EXPORT -int pw_core_proxy_disconnect(struct pw_core_proxy *proxy) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - pw_remote_destroy(remote); - return 0; -} - -SPA_EXPORT -struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, - uint32_t type, struct pw_properties *properties, - void *object, size_t user_data_size) -{ - struct pw_remote *remote = ((struct pw_proxy*)proxy)->remote; - return pw_remote_export(remote, type, properties, object, user_data_size); -} diff --git a/src/pipewire/remote.h b/src/pipewire/remote.h deleted file mode 100644 index fe297f5d8..000000000 --- a/src/pipewire/remote.h +++ /dev/null @@ -1,213 +0,0 @@ -/* PipeWire - * - * Copyright © 2018 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef PIPEWIRE_REMOTE_H -#define PIPEWIRE_REMOTE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** \page page_remote_api Remote API - * - * \section sec_remote_api_overview Overview - * - * The remote API allows you to connect to a remote PipeWire instance - * and perform actions on the PipeWire graph. This includes - * - * \li introspecting the objects on the instance - * \li Creating nodes - * \li Linking nodes on their ports - * \li providing media to the server for playback or consumption - * \li retrieving media from the remote instance - * - * \section sec_remote_api_loop Event Loop Abstraction - * - * Most API is asynchronous and based around an event loop. Methods will - * start an operation which will cause a state change of the \ref pw_remote - * object. Connect to the state_changed event to be notified of these - * state changes. - * - * The most convenient way to deal with the asynchronous calls is probably - * with the thread loop (See \subpage page_thread_loop for more details). - * - * \subsection ssec_remote_api_proxy Proxy - * - * Proxies are local representations of remote resources. They - * allow communication between local and remote objects. - * - * The \ref pw_remote maintains a list of all proxies, including a core - * proxy that is used to get access to other proxy objects. - * - * See also \subpage page_proxy - * - * \section sec_remote_api_remote Remote - * - * \subsection ssec_remote_create Create - * - * To create a new remote use pw_remote_new(). You will - * need to pass a local \ref pw_core implementation for event and - * data loop. - * - * A typical loop would be created with pw_thread_loop_new() but - * other implementation are possible. - * - * You will also need to pass properties for the remote. Use - * pw_fill_remote_properties() to get a default set of properties. - * - * After creating the remote, you can track the state of the remote - * by listening for the state_changed event. - * - * \subsection ssec_remote_api_remote_connect Connecting - * - * A remote must be connected before any operation can be issued. - * Calling pw_remote_connect() will initiate the connection procedure. - * - * When connecting, the remote will automatically create a core - * proxy to get access to the registry proxy and types. - * - * \subsection ssec_remote_api_remote_registry Registry - * - * \subpage page_registry - * - * - * \subsection ssec_remote_api_remote_disconnect Disconnect - * - * Use pw_remote_disconnect() to disconnect from the remote. - */ -/** \class pw_remote - * - * \brief Represents a connection with a remote PipeWire instance - * - * a \ref pw_remote is created and used to connect to a remote PipeWire - * instance. - * A \ref pw_proxy for the core object will automatically be created - * when connecting. - * - * See also \ref page_core_api - */ -struct pw_remote; - -#include -#include -#include -#include - -/** Create a new unconnected remote \memberof pw_remote - * \return a new unconnected remote */ -struct pw_remote * -pw_remote_new(struct pw_core *core, /**< a \ref pw_core */ - struct pw_properties *properties, /**< optional properties, ownership of - * the properties is taken.*/ - size_t user_data_size /**< extra user data size */); - -/** Destroy a remote \memberof pw_remote */ -void pw_remote_destroy(struct pw_remote *remote); - -/** Get the core used to construct this remote */ -struct pw_core *pw_remote_get_core(struct pw_remote *remote); - -/** Get the remote properties */ -const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote); - -/** Update properties */ -int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict); - -/** Get the user_data. The size was given in \ref pw_remote_new */ -void *pw_remote_get_user_data(struct pw_remote *remote); - -/** Connect to a remote PipeWire \memberof pw_remote - * \return 0 on success, < 0 on error */ -int pw_remote_connect(struct pw_remote *remote); - -/** Connect to a remote PipeWire on the given socket \memberof pw_remote - * \param fd the connected socket to use, the socket will be closed - * automatically on disconnect or error. - * \return 0 on success, < 0 on error */ -int pw_remote_connect_fd(struct pw_remote *remote, int fd); - -/** Steal the fd of the remote connection or < 0 on error. The remote - * will be in the unconnected state after this call. */ -int pw_remote_steal_fd(struct pw_remote *remote); - -/** Get the core proxy, can only be called when connected */ -struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote); -/** Get the client proxy, can only be called when connected */ -struct pw_client_proxy * pw_remote_get_client_proxy(struct pw_remote *remote); - -/** Get the proxy with the given id */ -struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id); - -/** Disconnect from the remote PipeWire. \memberof pw_remote */ -int pw_remote_disconnect(struct pw_remote *remote); - -/** run a local node in a remote graph */ -struct pw_proxy *pw_remote_export(struct pw_remote *remote, /**< the remote */ - uint32_t type, /**< the type of object */ - struct pw_properties *properties, /**< extra properties */ - void *object, /**< object to export */ - size_t user_data_size /**< extra user data */); - - -struct pw_core_proxy * -pw_core_connect(struct pw_core *core, /**< a \ref pw_core */ - struct pw_properties *properties, /**< optional properties, ownership of - * the properties is taken.*/ - size_t user_data_size /**< extra user data size */); - -struct pw_core_proxy * -pw_core_connect_fd(struct pw_core *core, /**< a \ref pw_core */ - int fd, /**< an fd */ - struct pw_properties *properties, /**< optional properties, ownership of - * the properties is taken.*/ - size_t user_data_size /**< extra user data size */); - -int pw_core_proxy_disconnect(struct pw_core_proxy *proxy); - -/** Get the client proxy */ -struct pw_client_proxy * pw_core_proxy_get_client_proxy(struct pw_core_proxy *proxy); - -struct pw_core * pw_core_proxy_get_core(struct pw_core_proxy *proxy); - -struct pw_remote * pw_core_proxy_get_remote(struct pw_core_proxy *proxy); - -struct pw_mempool * pw_core_proxy_get_mempool(struct pw_core_proxy *proxy); - -/** Get the proxy with the given id */ -struct pw_proxy *pw_core_proxy_find_proxy(struct pw_core_proxy *proxy, uint32_t id); - -struct pw_proxy *pw_core_proxy_export(struct pw_core_proxy *proxy, /**< the proxy */ - uint32_t type, /**< the type of object */ - struct pw_properties *properties, /**< extra properties */ - void *object, /**< object to export */ - size_t user_data_size /**< extra user data */); - - -#ifdef __cplusplus -} -#endif - -#endif /* PIPEWIRE_REMOTE_H */ diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 25ea11419..3e580e734 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -96,8 +96,6 @@ struct stream { enum spa_direction direction; enum pw_stream_flags flags; - struct spa_hook remote_listener; - struct pw_node *node; struct spa_port_info port_info; @@ -1068,8 +1066,6 @@ stream_new(struct pw_core *core, const char *name, impl->core = core; -// spa_list_append(&remote->stream_list, &this->link); - return impl; error_properties: @@ -1169,7 +1165,6 @@ void pw_stream_destroy(struct pw_stream *stream) spa_hook_remove(&stream->core_listener); stream->core_proxy = NULL; } -// spa_list_remove(&stream->link); clear_params(impl, SPA_ID_INVALID); diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 342343679..3a8339d85 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -48,7 +48,7 @@ extern "C" { * * For more complicated nodes such as filters or ports with multiple * inputs and/or outputs you will need to use the pw_filter or make - * a pw_node yourself and export it with \ref pw_remote_export. + * a pw_node yourself and export it with \ref pw_core_proxy_export. * * \section sec_create Create * @@ -152,7 +152,7 @@ struct pw_stream; #include #include -#include +#include /** \enum pw_stream_state The state of a stream \memberof pw_stream */ enum pw_stream_state { diff --git a/src/tests/test-cpp.cpp b/src/tests/test-cpp.cpp index fca31ae1e..824dc4e18 100644 --- a/src/tests/test-cpp.cpp +++ b/src/tests/test-cpp.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/tests/test-remote.c b/src/tests/test-remote.c deleted file mode 100644 index 9083fafc2..000000000 --- a/src/tests/test-remote.c +++ /dev/null @@ -1,186 +0,0 @@ -/* PipeWire - * - * Copyright © 2019 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -#define TEST_FUNC(a,b,func) \ -do { \ - a.func = b.func; \ - spa_assert(SPA_PTRDIFF(&a.func, &a) == SPA_PTRDIFF(&b.func, &b)); \ -} while(0) - -static void test_abi(void) -{ - struct pw_remote_events ev; - struct { - uint32_t version; - void (*destroy) (void *data); - void (*state_changed) (void *data, enum pw_remote_state old, - enum pw_remote_state state, const char *error); - } test = { PW_VERSION_REMOTE_EVENTS, NULL }; - - TEST_FUNC(ev, test, destroy); - TEST_FUNC(ev, test, state_changed); - - spa_assert(PW_VERSION_REMOTE_EVENTS == 0); - spa_assert(sizeof(ev) == sizeof(test)); - - spa_assert(PW_REMOTE_STATE_ERROR == -1); - spa_assert(PW_REMOTE_STATE_UNCONNECTED == 0); - spa_assert(PW_REMOTE_STATE_CONNECTING == 1); - spa_assert(PW_REMOTE_STATE_CONNECTED == 2); - - spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_ERROR) != NULL); - spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_UNCONNECTED) != NULL); - spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_CONNECTING) != NULL); - spa_assert(pw_remote_state_as_string(PW_REMOTE_STATE_CONNECTED) != NULL); -} - -static void remote_destroy_error(void *data) -{ - spa_assert_not_reached(); -} -static void remote_state_changed_error(void *data, enum pw_remote_state old, - enum pw_remote_state state, const char *error) -{ - spa_assert_not_reached(); -} - -static const struct pw_remote_events remote_events_error = -{ - PW_VERSION_REMOTE_EVENTS, - .destroy = remote_destroy_error, - .state_changed = remote_state_changed_error, -}; - -static int destroy_count = 0; -static void remote_destroy_count(void *data) -{ - destroy_count++; -} -static void test_create(void) -{ - struct pw_main_loop *loop; - struct pw_core *core; - struct pw_remote *remote; - struct pw_remote_events remote_events = remote_events_error; - struct spa_hook listener = { 0, }; - const char *error = NULL; - - loop = pw_main_loop_new(NULL); - core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 12); - - remote = pw_remote_new(core, NULL, 12); - spa_assert(remote != NULL); - pw_remote_add_listener(remote, &listener, &remote_events, remote); - - /* check core */ - spa_assert(pw_remote_get_core(remote) == core); - /* check user data */ - spa_assert(pw_remote_get_user_data(remote) != NULL); - /* check state */ - spa_assert(pw_remote_get_state(remote, &error) == PW_REMOTE_STATE_UNCONNECTED); - spa_assert(error == NULL); - - /* check core proxy, only available when connected */ - spa_assert(pw_remote_get_core_proxy(remote) == NULL); - - /* check some non-existing proxies */ - spa_assert(pw_remote_find_proxy(remote, 0) == NULL); - spa_assert(pw_remote_find_proxy(remote, 5) == NULL); - - /* check destroy */ - destroy_count = 0; - remote_events.destroy = remote_destroy_count; - pw_remote_destroy(remote); - spa_assert(destroy_count == 1); - - pw_core_destroy(core); - pw_main_loop_destroy(loop); -} - -static void test_properties(void) -{ - struct pw_main_loop *loop; - struct pw_core *core; - const struct pw_properties *props; - struct pw_remote *remote; - struct pw_remote_events remote_events = remote_events_error; - struct spa_hook listener = { NULL, }; - struct spa_dict_item items[3]; - - loop = pw_main_loop_new(NULL); - core = pw_core_new(pw_main_loop_get_loop(loop), NULL, 0); - remote = pw_remote_new(core, - pw_properties_new("foo", "bar", - "biz", "fuzz", - NULL), - 0); - spa_assert(remote != NULL); - spa_assert(pw_remote_get_user_data(remote) == NULL); - pw_remote_add_listener(remote, &listener, &remote_events, remote); - - props = pw_remote_get_properties(remote); - spa_assert(props != NULL); - spa_assert(!strcmp(pw_properties_get(props, "foo"), "bar")); - spa_assert(!strcmp(pw_properties_get(props, "biz"), "fuzz")); - spa_assert(pw_properties_get(props, "buzz") == NULL); - - /* remove foo */ - items[0] = SPA_DICT_ITEM_INIT("foo", NULL); - /* change biz */ - items[1] = SPA_DICT_ITEM_INIT("biz", "buzz"); - /* add buzz */ - items[2] = SPA_DICT_ITEM_INIT("buzz", "frizz"); - /* update properties does not emit the info_changed signal - * because that is only emited when the remote core properties - * changed */ - pw_remote_update_properties(remote, &SPA_DICT_INIT(items, 3)); - - spa_assert(props == pw_remote_get_properties(remote)); - spa_assert(pw_properties_get(props, "foo") == NULL); - spa_assert(!strcmp(pw_properties_get(props, "biz"), "buzz")); - spa_assert(!strcmp(pw_properties_get(props, "buzz"), "frizz")); - - /* check destroy */ - destroy_count = 0; - remote_events.destroy = remote_destroy_count; - pw_core_destroy(core); - spa_assert(destroy_count == 1); - - pw_main_loop_destroy(loop); -} - -int main(int argc, char *argv[]) -{ - pw_init(&argc, &argv); - - test_abi(); - test_create(); - test_properties(); - - return 0; -} diff --git a/src/tools/pipewire-dot.c b/src/tools/pipewire-dot.c index 86f583c26..364af7031 100644 --- a/src/tools/pipewire-dot.c +++ b/src/tools/pipewire-dot.c @@ -33,7 +33,6 @@ #include #include -#include #include #include