mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	remote: remove the remote
Mostly rename pw_remote_* to pw_core_proxy_*
This commit is contained in:
		
							parent
							
								
									3d79970d88
								
							
						
					
					
						commit
						ca6f1bd2f1
					
				
					 20 changed files with 608 additions and 1063 deletions
				
			
		| 
						 | 
					@ -581,7 +581,6 @@ on_remote_data(void *data, int fd, uint32_t mask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *impl = data;
 | 
						struct client *impl = data;
 | 
				
			||||||
	struct pw_core_proxy *this = impl->this.core_proxy;
 | 
						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_protocol_native_connection *conn = impl->connection;
 | 
				
			||||||
	struct pw_core *core = pw_core_proxy_get_core(this);
 | 
						struct pw_core *core = pw_core_proxy_get_core(this);
 | 
				
			||||||
	struct pw_loop *loop = pw_core_get_main_loop(core);
 | 
						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",
 | 
					                        pw_log_trace(NAME" %p: got message %d from %u seq:%d",
 | 
				
			||||||
					this, msg->opcode, msg->id, msg->seq);
 | 
										this, msg->opcode, msg->id, msg->seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			remote->recv_seq = msg->seq;
 | 
								this->recv_seq = msg->seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (debug_messages) {
 | 
								if (debug_messages) {
 | 
				
			||||||
				fprintf(stderr, "<<<<<<<<< in: id:%d op:%d size:%d seq:%d\n",
 | 
									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_log_error(NAME" %p: got connection error %d (%s)", impl, res, spa_strerror(res));
 | 
				
			||||||
	pw_proxy_notify((struct pw_proxy*)this,
 | 
						pw_proxy_notify((struct pw_proxy*)this,
 | 
				
			||||||
			struct pw_core_proxy_events, error, 0, 0,
 | 
								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);
 | 
						pw_loop_destroy_source(loop, impl->source);
 | 
				
			||||||
	impl->source = NULL;
 | 
						impl->source = NULL;
 | 
				
			||||||
	pw_core_proxy_disconnect(this);
 | 
						pw_core_proxy_disconnect(this);
 | 
				
			||||||
| 
						 | 
					@ -924,28 +923,28 @@ const static struct pw_protocol_implementaton protocol_impl = {
 | 
				
			||||||
static struct spa_pod_builder *
 | 
					static struct spa_pod_builder *
 | 
				
			||||||
impl_ext_begin_proxy(struct pw_proxy *proxy, uint8_t opcode, struct pw_protocol_native_message **msg)
 | 
					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);
 | 
						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)
 | 
					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);
 | 
						return pw_protocol_native_connection_add_fd(impl->connection, fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int impl_ext_get_proxy_fd(struct pw_proxy *proxy, uint32_t index)
 | 
					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);
 | 
						return pw_protocol_native_connection_get_fd(impl->connection, index);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int impl_ext_end_proxy(struct pw_proxy *proxy,
 | 
					static int impl_ext_end_proxy(struct pw_proxy *proxy,
 | 
				
			||||||
			       struct spa_pod_builder *builder)
 | 
								       struct spa_pod_builder *builder)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *impl = SPA_CONTAINER_OF(proxy->remote->conn, struct client, this);
 | 
						struct pw_core_proxy *core_proxy = proxy->core_proxy;
 | 
				
			||||||
	struct pw_remote *remote = proxy->remote;
 | 
						struct client *impl = SPA_CONTAINER_OF(core_proxy->conn, struct client, this);
 | 
				
			||||||
	return remote->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
 | 
						return core_proxy->send_seq = pw_protocol_native_connection_end(impl->connection, builder);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct spa_pod_builder *
 | 
					static struct spa_pod_builder *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										429
									
								
								src/pipewire/core-proxy.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								src/pipewire/core-proxy.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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 <stdio.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <sys/socket.h>
 | 
				
			||||||
 | 
					#include <sys/un.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <sys/mman.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <spa/pod/parser.h>
 | 
				
			||||||
 | 
					#include <spa/debug/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										86
									
								
								src/pipewire/core-proxy.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/pipewire/core-proxy.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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 <spa/utils/hook.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <pipewire/core.h>
 | 
				
			||||||
 | 
					#include <pipewire/properties.h>
 | 
				
			||||||
 | 
					#include <pipewire/node.h>
 | 
				
			||||||
 | 
					#include <pipewire/proxy.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 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 */
 | 
				
			||||||
| 
						 | 
					@ -570,7 +570,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop,
 | 
				
			||||||
	pw_map_init(&this->globals, 128, 32);
 | 
						pw_map_init(&this->globals, 128, 32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_init(&this->protocol_list);
 | 
						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->registry_resource_list);
 | 
				
			||||||
	spa_list_init(&this->global_list);
 | 
						spa_list_init(&this->global_list);
 | 
				
			||||||
	spa_list_init(&this->module_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_global *global;
 | 
				
			||||||
	struct pw_module *module;
 | 
						struct pw_module *module;
 | 
				
			||||||
	struct pw_device *device;
 | 
						struct pw_device *device;
 | 
				
			||||||
	struct pw_remote *remote;
 | 
						struct pw_core_proxy *core_proxy;
 | 
				
			||||||
	struct pw_resource *resource;
 | 
						struct pw_resource *resource;
 | 
				
			||||||
	struct pw_node *node;
 | 
						struct pw_node *node;
 | 
				
			||||||
	struct factory_entry *entry;
 | 
						struct factory_entry *entry;
 | 
				
			||||||
| 
						 | 
					@ -670,8 +670,8 @@ void pw_core_destroy(struct pw_core *core)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&core->global_listener);
 | 
						spa_hook_remove(&core->global_listener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_consume(remote, &core->remote_list, link)
 | 
						spa_list_consume(core_proxy, &core->core_proxy_list, link)
 | 
				
			||||||
		pw_remote_destroy(remote);
 | 
							pw_core_proxy_disconnect(core_proxy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_consume(module, &core->module_list, link)
 | 
						spa_list_consume(module, &core->module_list, link)
 | 
				
			||||||
		pw_module_destroy(module);
 | 
							pw_module_destroy(module);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ struct pw_core;
 | 
				
			||||||
#include <pipewire/client.h>
 | 
					#include <pipewire/client.h>
 | 
				
			||||||
#include <pipewire/introspect.h>
 | 
					#include <pipewire/introspect.h>
 | 
				
			||||||
#include <pipewire/interfaces.h>
 | 
					#include <pipewire/interfaces.h>
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					#include <pipewire/core-proxy.h>
 | 
				
			||||||
#include <pipewire/global.h>
 | 
					#include <pipewire/global.h>
 | 
				
			||||||
#include <pipewire/loop.h>
 | 
					#include <pipewire/loop.h>
 | 
				
			||||||
#include <pipewire/factory.h>
 | 
					#include <pipewire/factory.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -947,8 +947,6 @@ filter_new(struct pw_core *core, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->core = core;
 | 
						impl->core = core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	spa_list_append(&remote->filter_list, &this->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return impl;
 | 
						return impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_properties:
 | 
					error_properties:
 | 
				
			||||||
| 
						 | 
					@ -1048,7 +1046,6 @@ void pw_filter_destroy(struct pw_filter *filter)
 | 
				
			||||||
		spa_hook_remove(&filter->core_listener);
 | 
							spa_hook_remove(&filter->core_listener);
 | 
				
			||||||
		filter->core_proxy = NULL;
 | 
							filter->core_proxy = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
//	spa_list_remove(&filter->link);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clear_params(impl, NULL, SPA_ID_INVALID);
 | 
						clear_params(impl, NULL, SPA_ID_INVALID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ struct pw_filter;
 | 
				
			||||||
#include <spa/node/io.h>
 | 
					#include <spa/node/io.h>
 | 
				
			||||||
#include <spa/param/param.h>
 | 
					#include <spa/param/param.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					#include <pipewire/core-proxy.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \enum pw_filter_state The state of a filter \memberof pw_filter */
 | 
					/** \enum pw_filter_state The state of a filter \memberof pw_filter */
 | 
				
			||||||
enum pw_filter_state {
 | 
					enum pw_filter_state {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pipewire/pipewire.h"
 | 
					#include "pipewire/pipewire.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pipewire/remote.h"
 | 
					#include "pipewire/core-proxy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
const char *pw_node_state_as_string(enum pw_node_state state)
 | 
					const char *pw_node_state_as_string(enum pw_node_state state)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ pipewire_headers = [
 | 
				
			||||||
  'properties.h',
 | 
					  'properties.h',
 | 
				
			||||||
  'protocol.h',
 | 
					  'protocol.h',
 | 
				
			||||||
  'proxy.h',
 | 
					  'proxy.h',
 | 
				
			||||||
  'remote.h',
 | 
					  'core-proxy.h',
 | 
				
			||||||
  'resource.h',
 | 
					  'resource.h',
 | 
				
			||||||
  'stream.h',
 | 
					  'stream.h',
 | 
				
			||||||
  'thread-loop.h',
 | 
					  'thread-loop.h',
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ pipewire_sources = [
 | 
				
			||||||
  'properties.c',
 | 
					  'properties.c',
 | 
				
			||||||
  'protocol.c',
 | 
					  'protocol.c',
 | 
				
			||||||
  'proxy.c',
 | 
					  'proxy.c',
 | 
				
			||||||
  'remote.c',
 | 
					  'core-proxy.c',
 | 
				
			||||||
  'resource.c',
 | 
					  'resource.c',
 | 
				
			||||||
  'stream.c',
 | 
					  'stream.c',
 | 
				
			||||||
  'thread-loop.c',
 | 
					  'thread-loop.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ extern "C" {
 | 
				
			||||||
#include <pipewire/port.h>
 | 
					#include <pipewire/port.h>
 | 
				
			||||||
#include <pipewire/properties.h>
 | 
					#include <pipewire/properties.h>
 | 
				
			||||||
#include <pipewire/proxy.h>
 | 
					#include <pipewire/proxy.h>
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					#include <pipewire/core-proxy.h>
 | 
				
			||||||
#include <pipewire/resource.h>
 | 
					#include <pipewire/resource.h>
 | 
				
			||||||
#include <pipewire/stream.h>
 | 
					#include <pipewire/stream.h>
 | 
				
			||||||
#include <pipewire/thread-loop.h>
 | 
					#include <pipewire/thread-loop.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,6 @@ extern "C" {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pipewire/buffers.h"
 | 
					#include "pipewire/buffers.h"
 | 
				
			||||||
#include "pipewire/map.h"
 | 
					#include "pipewire/map.h"
 | 
				
			||||||
#include "pipewire/remote.h"
 | 
					 | 
				
			||||||
#include "pipewire/mem.h"
 | 
					#include "pipewire/mem.h"
 | 
				
			||||||
#include "pipewire/introspect.h"
 | 
					#include "pipewire/introspect.h"
 | 
				
			||||||
#include "pipewire/interfaces.h"
 | 
					#include "pipewire/interfaces.h"
 | 
				
			||||||
| 
						 | 
					@ -222,7 +221,7 @@ struct pw_core {
 | 
				
			||||||
	struct pw_map globals;			/**< map of globals */
 | 
						struct pw_map globals;			/**< map of globals */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_list protocol_list;		/**< list of protocols */
 | 
						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 registry_resource_list;	/**< list of registry resources */
 | 
				
			||||||
	struct spa_list module_list;		/**< list of modules */
 | 
						struct spa_list module_list;		/**< list of modules */
 | 
				
			||||||
	struct spa_list device_list;		/**< list of devices */
 | 
						struct spa_list device_list;		/**< list of devices */
 | 
				
			||||||
| 
						 | 
					@ -713,7 +712,7 @@ struct pw_resource {
 | 
				
			||||||
struct pw_proxy {
 | 
					struct pw_proxy {
 | 
				
			||||||
	struct spa_interface impl;	/**< object implementation */
 | 
						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 id;			/**< client side id */
 | 
				
			||||||
	uint32_t type;			/**< type of the interface */
 | 
						uint32_t type;			/**< type of the interface */
 | 
				
			||||||
| 
						 | 
					@ -731,17 +730,18 @@ struct pw_proxy {
 | 
				
			||||||
	void *user_data;		/**< extra user data */
 | 
						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__)
 | 
					struct pw_core_proxy {
 | 
				
			||||||
#define pw_remote_emit_destroy(r)		pw_remote_emit(r, destroy, 0)
 | 
						struct pw_proxy proxy;
 | 
				
			||||||
#define pw_remote_emit_state_changed(r,o,s,e)	pw_remote_emit(r, state_changed, 0, o, s, e)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct pw_remote {
 | 
					 | 
				
			||||||
	struct pw_core *core;			/**< core */
 | 
						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_properties *properties;	/**< extra properties */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct pw_mempool *pool;		/**< memory pool */
 | 
						struct pw_mempool *pool;		/**< memory pool */
 | 
				
			||||||
	struct pw_core_proxy *core_proxy;	/**< proxy for the core object */
 | 
						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
 | 
						struct pw_map objects;			/**< map of client side proxy objects
 | 
				
			||||||
						 *   indexed with the client id */
 | 
											 *   indexed with the client id */
 | 
				
			||||||
	struct pw_client_proxy *client_proxy;	/**< proxy for the client object */
 | 
						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);
 | 
					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);
 | 
					int pw_proxy_install_marshal(struct pw_proxy *proxy, bool implementor);
 | 
				
			||||||
void pw_proxy_remove(struct pw_proxy *proxy);
 | 
					void pw_proxy_remove(struct pw_proxy *proxy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,6 @@
 | 
				
			||||||
#include <pipewire/log.h>
 | 
					#include <pipewire/log.h>
 | 
				
			||||||
#include <pipewire/proxy.h>
 | 
					#include <pipewire/proxy.h>
 | 
				
			||||||
#include <pipewire/core.h>
 | 
					#include <pipewire/core.h>
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					 | 
				
			||||||
#include <pipewire/private.h>
 | 
					#include <pipewire/private.h>
 | 
				
			||||||
#include <pipewire/type.h>
 | 
					#include <pipewire/type.h>
 | 
				
			||||||
#include <pipewire/interfaces.h>
 | 
					#include <pipewire/interfaces.h>
 | 
				
			||||||
| 
						 | 
					@ -40,6 +39,38 @@ struct proxy {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
/** \endcond */
 | 
					/** \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
 | 
					/** Create a proxy object with a given id and type
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param factory another proxy object that serves as a factory
 | 
					 * \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
 | 
					 * 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.
 | 
					 * proxy object will have an id assigned from the client id space.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \sa pw_remote
 | 
					 * \sa pw_core_proxy
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \memberof pw_proxy
 | 
					 * \memberof pw_proxy
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -61,7 +92,6 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct proxy *impl;
 | 
						struct proxy *impl;
 | 
				
			||||||
	struct pw_proxy *this;
 | 
						struct pw_proxy *this;
 | 
				
			||||||
	struct pw_remote *remote = factory->remote;
 | 
					 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct proxy) + user_data_size);
 | 
						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;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this = &impl->this;
 | 
						this = &impl->this;
 | 
				
			||||||
	this->remote = remote;
 | 
						this->core_proxy = factory->core_proxy;
 | 
				
			||||||
	this->refcount = 1;
 | 
					 | 
				
			||||||
	this->type = type;
 | 
					 | 
				
			||||||
	this->version = version;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->id = pw_map_insert_new(&remote->objects, this);
 | 
						if ((res = pw_proxy_init(this, type, version)) < 0)
 | 
				
			||||||
	if (this->id == SPA_ID_INVALID) {
 | 
							goto error_init;
 | 
				
			||||||
		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 (user_data_size > 0)
 | 
						if (user_data_size > 0)
 | 
				
			||||||
		this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
 | 
							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,
 | 
								this, this->id,
 | 
				
			||||||
			spa_debug_type_find_name(pw_type_info(), type), version,
 | 
								spa_debug_type_find_name(pw_type_info(), type), version,
 | 
				
			||||||
			remote, this->marshal);
 | 
								this->core_proxy, this->marshal);
 | 
				
			||||||
	return this;
 | 
						return this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_clean:
 | 
					error_init:
 | 
				
			||||||
	free(impl);
 | 
						free(impl);
 | 
				
			||||||
	errno = -res;
 | 
						errno = -res;
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
| 
						 | 
					@ -109,10 +122,10 @@ error_clean:
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
int pw_proxy_install_marshal(struct pw_proxy *this, bool implementor)
 | 
					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;
 | 
						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,
 | 
								this->type, this->version,
 | 
				
			||||||
			implementor ? PW_PROTOCOL_MARSHAL_FLAG_IMPL : 0);
 | 
								implementor ? PW_PROTOCOL_MARSHAL_FLAG_IMPL : 0);
 | 
				
			||||||
	if (marshal == NULL)
 | 
						if (marshal == NULL)
 | 
				
			||||||
| 
						 | 
					@ -147,15 +160,15 @@ uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPA_EXPORT
 | 
					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
 | 
					SPA_EXPORT
 | 
				
			||||||
struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy)
 | 
					struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return proxy->remote->conn->protocol;
 | 
						return proxy->core_proxy->conn->protocol;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
| 
						 | 
					@ -180,14 +193,14 @@ void pw_proxy_add_object_listener(struct pw_proxy *proxy,
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * \param proxy Proxy object to destroy
 | 
					 * \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
 | 
					 *       decides to destroy the server side object
 | 
				
			||||||
 * \memberof pw_proxy
 | 
					 * \memberof pw_proxy
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SPA_EXPORT
 | 
					SPA_EXPORT
 | 
				
			||||||
void pw_proxy_destroy(struct pw_proxy *proxy)
 | 
					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) {
 | 
						if (!proxy->zombie) {
 | 
				
			||||||
		pw_log_debug(NAME" %p: destroy %u", proxy, proxy->id);
 | 
							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 (!proxy->removed) {
 | 
				
			||||||
		/* if the server did not remove this proxy, remove ourselves
 | 
							/* if the server did not remove this proxy, remove ourselves
 | 
				
			||||||
		 * from the proxy objects and schedule a destroy. */
 | 
							 * from the proxy objects and schedule a destroy. */
 | 
				
			||||||
		if (remote->core_proxy) {
 | 
							if (core_proxy) {
 | 
				
			||||||
			proxy->zombie = true;
 | 
								proxy->zombie = true;
 | 
				
			||||||
			pw_core_proxy_destroy(remote->core_proxy, proxy);
 | 
								pw_core_proxy_destroy(core_proxy, proxy);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			proxy->removed = true;
 | 
								proxy->removed = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (proxy->removed) {
 | 
						if (proxy->removed) {
 | 
				
			||||||
		pw_map_remove(&remote->objects, proxy->id);
 | 
							pw_map_remove(&core_proxy->objects, proxy->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_proxy_unref(proxy);
 | 
							pw_proxy_unref(proxy);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -230,10 +243,10 @@ SPA_EXPORT
 | 
				
			||||||
int pw_proxy_sync(struct pw_proxy *proxy, int seq)
 | 
					int pw_proxy_sync(struct pw_proxy *proxy, int seq)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int res = -EIO;
 | 
						int res = -EIO;
 | 
				
			||||||
	struct pw_remote *remote = proxy->remote;
 | 
						struct pw_core_proxy *core_proxy = proxy->core_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (remote->core_proxy != NULL) {
 | 
						if (core_proxy != NULL) {
 | 
				
			||||||
		res = pw_core_proxy_sync(remote->core_proxy, proxy->id, seq);
 | 
							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);
 | 
							pw_log_debug(NAME" %p: %u seq:%d sync %u", proxy, proxy->id, seq, res);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
| 
						 | 
					@ -244,12 +257,12 @@ int pw_proxy_errorf(struct pw_proxy *proxy, int res, const char *error, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	va_list ap;
 | 
						va_list ap;
 | 
				
			||||||
	int r = -EIO;
 | 
						int r = -EIO;
 | 
				
			||||||
	struct pw_remote *remote = proxy->remote;
 | 
						struct pw_core_proxy *core_proxy = proxy->core_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	va_start(ap, error);
 | 
						va_start(ap, error);
 | 
				
			||||||
	if (remote->core_proxy != NULL)
 | 
						if (core_proxy != NULL)
 | 
				
			||||||
		r = pw_core_proxy_errorv(remote->core_proxy, proxy->id,
 | 
							r = pw_core_proxy_errorv(core_proxy, proxy->id,
 | 
				
			||||||
				remote->recv_seq, res, error, ap);
 | 
									core_proxy->recv_seq, res, error, ap);
 | 
				
			||||||
	va_end(ap);
 | 
						va_end(ap);
 | 
				
			||||||
	return r;
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -258,10 +271,10 @@ SPA_EXPORT
 | 
				
			||||||
int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error)
 | 
					int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int r = -EIO;
 | 
						int r = -EIO;
 | 
				
			||||||
	struct pw_remote *remote = proxy->remote;
 | 
						struct pw_core_proxy *core_proxy = proxy->core_proxy;
 | 
				
			||||||
	if (remote->core_proxy != NULL)
 | 
						if (core_proxy != NULL)
 | 
				
			||||||
		r = pw_core_proxy_error(remote->core_proxy, proxy->id,
 | 
							r = pw_core_proxy_error(core_proxy, proxy->id,
 | 
				
			||||||
				remote->recv_seq, res, error);
 | 
									core_proxy->recv_seq, res, error);
 | 
				
			||||||
	return r;
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,9 +43,8 @@ extern "C" {
 | 
				
			||||||
 * \section sec_page_proxy_core Core proxy
 | 
					 * \section sec_page_proxy_core Core proxy
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * A proxy for a remote core object can be obtained by making
 | 
					 * A proxy for a remote core object can be obtained by making
 | 
				
			||||||
 * a remote connection. See \ref pw_page_remote_api
 | 
					 * a remote connection with \ref pw_core_connect.
 | 
				
			||||||
 *
 | 
					 * See \ref pw_page_remote_api
 | 
				
			||||||
 * A pw_core_proxy can then be retrieved with \ref pw_remote_get_core_proxy
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Some methods on proxy object allow creation of more proxy objects or
 | 
					 * Some methods on proxy object allow creation of more proxy objects or
 | 
				
			||||||
 * create a binding between a local proxy and global resource.
 | 
					 * 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 */
 | 
					/** Get the type and version of the proxy */
 | 
				
			||||||
uint32_t pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version);
 | 
					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 */
 | 
					/** Get the protocol used for the proxy */
 | 
				
			||||||
struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy);
 | 
					struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 <stdio.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					 | 
				
			||||||
#include <sys/un.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <sys/mman.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <spa/pod/parser.h>
 | 
					 | 
				
			||||||
#include <spa/debug/types.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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 <spa/utils/hook.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** \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 <pipewire/core.h>
 | 
					 | 
				
			||||||
#include <pipewire/properties.h>
 | 
					 | 
				
			||||||
#include <pipewire/node.h>
 | 
					 | 
				
			||||||
#include <pipewire/proxy.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 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 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -96,8 +96,6 @@ struct stream {
 | 
				
			||||||
	enum spa_direction direction;
 | 
						enum spa_direction direction;
 | 
				
			||||||
	enum pw_stream_flags flags;
 | 
						enum pw_stream_flags flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_hook remote_listener;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct pw_node *node;
 | 
						struct pw_node *node;
 | 
				
			||||||
	struct spa_port_info port_info;
 | 
						struct spa_port_info port_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1068,8 +1066,6 @@ stream_new(struct pw_core *core, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->core = core;
 | 
						impl->core = core;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//	spa_list_append(&remote->stream_list, &this->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return impl;
 | 
						return impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_properties:
 | 
					error_properties:
 | 
				
			||||||
| 
						 | 
					@ -1169,7 +1165,6 @@ void pw_stream_destroy(struct pw_stream *stream)
 | 
				
			||||||
		spa_hook_remove(&stream->core_listener);
 | 
							spa_hook_remove(&stream->core_listener);
 | 
				
			||||||
		stream->core_proxy = NULL;
 | 
							stream->core_proxy = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
//	spa_list_remove(&stream->link);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clear_params(impl, SPA_ID_INVALID);
 | 
						clear_params(impl, SPA_ID_INVALID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ extern "C" {
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * For more complicated nodes such as filters or ports with multiple
 | 
					 * 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
 | 
					 * 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
 | 
					 * \section sec_create Create
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -152,7 +152,7 @@ struct pw_stream;
 | 
				
			||||||
#include <spa/buffer/buffer.h>
 | 
					#include <spa/buffer/buffer.h>
 | 
				
			||||||
#include <spa/param/param.h>
 | 
					#include <spa/param/param.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					#include <pipewire/core-proxy.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \enum pw_stream_state The state of a stream \memberof pw_stream */
 | 
					/** \enum pw_stream_state The state of a stream \memberof pw_stream */
 | 
				
			||||||
enum pw_stream_state {
 | 
					enum pw_stream_state {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@
 | 
				
			||||||
#include <pipewire/properties.h>
 | 
					#include <pipewire/properties.h>
 | 
				
			||||||
#include <pipewire/protocol.h>
 | 
					#include <pipewire/protocol.h>
 | 
				
			||||||
#include <pipewire/proxy.h>
 | 
					#include <pipewire/proxy.h>
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					#include <pipewire/core-proxy.h>
 | 
				
			||||||
#include <pipewire/resource.h>
 | 
					#include <pipewire/resource.h>
 | 
				
			||||||
#include <pipewire/stream.h>
 | 
					#include <pipewire/stream.h>
 | 
				
			||||||
#include <pipewire/thread-loop.h>
 | 
					#include <pipewire/thread-loop.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 <pipewire/pipewire.h>
 | 
					 | 
				
			||||||
#include <pipewire/main-loop.h>
 | 
					 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <pipewire/interfaces.h>
 | 
					#include <pipewire/interfaces.h>
 | 
				
			||||||
#include <pipewire/type.h>
 | 
					#include <pipewire/type.h>
 | 
				
			||||||
#include <pipewire/remote.h>
 | 
					 | 
				
			||||||
#include <pipewire/main-loop.h>
 | 
					#include <pipewire/main-loop.h>
 | 
				
			||||||
#include <pipewire/pipewire.h>
 | 
					#include <pipewire/pipewire.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue