mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pipewire: improve memory cleanup
Add method to unload a spa interface. Various other memory cleanups
This commit is contained in:
		
							parent
							
								
									0dc036ac84
								
							
						
					
					
						commit
						d165b3b842
					
				
					 8 changed files with 362 additions and 80 deletions
				
			
		| 
						 | 
					@ -200,6 +200,13 @@ static int make_link(struct impl *this,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void clean_link(struct impl *this, struct link *link)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (link->buffers)
 | 
				
			||||||
 | 
							free(link->buffers);
 | 
				
			||||||
 | 
						link->buffers = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int negotiate_link_format(struct impl *this, struct link *link)
 | 
					static int negotiate_link_format(struct impl *this, struct link *link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct type *t = &this->type;
 | 
						struct type *t = &this->type;
 | 
				
			||||||
| 
						 | 
					@ -398,6 +405,8 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
 | 
				
			||||||
		aligns[i] = align;
 | 
							aligns[i] = align;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (link->buffers)
 | 
				
			||||||
 | 
							free(link->buffers);
 | 
				
			||||||
	link->buffers = spa_buffer_alloc_array(buffers, flags, 0, NULL, blocks, datas, aligns);
 | 
						link->buffers = spa_buffer_alloc_array(buffers, flags, 0, NULL, blocks, datas, aligns);
 | 
				
			||||||
	if (link->buffers == NULL)
 | 
						if (link->buffers == NULL)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -437,6 +446,13 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void clean_buffers(struct impl *this)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < this->n_links; i++)
 | 
				
			||||||
 | 
							clean_link(this, &this->links[i]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int setup_buffers(struct impl *this, enum spa_direction direction)
 | 
					static int setup_buffers(struct impl *this, enum spa_direction direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i, res;
 | 
						int i, res;
 | 
				
			||||||
| 
						 | 
					@ -847,6 +863,13 @@ static int impl_get_interface(struct spa_handle *handle, uint32_t interface_id,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int impl_clear(struct spa_handle *handle)
 | 
					static int impl_clear(struct spa_handle *handle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct impl *this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_return_val_if_fail(handle != NULL, -EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this = (struct impl *) handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clean_buffers(this);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,6 +327,8 @@ static int impl_clear(struct spa_handle *handle)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *this = (struct impl *) handle;
 | 
						struct impl *this = (struct impl *) handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->uitem.udevice)
 | 
				
			||||||
 | 
							udev_device_unref(this->uitem.udevice);
 | 
				
			||||||
	if (this->enumerate)
 | 
						if (this->enumerate)
 | 
				
			||||||
		udev_enumerate_unref(this->enumerate);
 | 
							udev_enumerate_unref(this->enumerate);
 | 
				
			||||||
	if (this->umonitor)
 | 
						if (this->umonitor)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1084,6 +1084,10 @@ static int node_clear(struct node *this)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < this->n_params; i++)
 | 
				
			||||||
 | 
							free(this->params[i]);
 | 
				
			||||||
 | 
						free(this->params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < MAX_INPUTS; i++) {
 | 
						for (i = 0; i < MAX_INPUTS; i++) {
 | 
				
			||||||
		if (this->in_ports[i].valid)
 | 
							if (this->in_ports[i].valid)
 | 
				
			||||||
			clear_port(this, &this->in_ports[i], SPA_DIRECTION_INPUT, i);
 | 
								clear_port(this, &this->in_ports[i], SPA_DIRECTION_INPUT, i);
 | 
				
			||||||
| 
						 | 
					@ -1186,6 +1190,8 @@ static void node_free(void *data)
 | 
				
			||||||
	if (impl->io_areas)
 | 
						if (impl->io_areas)
 | 
				
			||||||
		pw_memblock_free(impl->io_areas);
 | 
							pw_memblock_free(impl->io_areas);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_map_clear(&impl->io_map);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->fds[0] != -1)
 | 
						if (impl->fds[0] != -1)
 | 
				
			||||||
		close(impl->fds[0]);
 | 
							close(impl->fds[0]);
 | 
				
			||||||
	if (impl->fds[1] != -1)
 | 
						if (impl->fds[1] != -1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -442,14 +442,20 @@ static int negotiate_buffers(struct impl *impl)
 | 
				
			||||||
	spa_buffer_alloc_fill_info(&info, 0, NULL, blocks, datas, aligns);
 | 
						spa_buffer_alloc_fill_info(&info, 0, NULL, blocks, datas, aligns);
 | 
				
			||||||
	info.skel_size = SPA_ROUND_UP_N(info.skel_size, 16);
 | 
						info.skel_size = SPA_ROUND_UP_N(info.skel_size, 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl->buffers)
 | 
				
			||||||
 | 
							free(impl->buffers);
 | 
				
			||||||
	impl->buffers = calloc(blocks, sizeof(struct spa_buffer *) + info.skel_size);
 | 
						impl->buffers = calloc(blocks, sizeof(struct spa_buffer *) + info.skel_size);
 | 
				
			||||||
	if (impl->buffers == NULL)
 | 
						if (impl->buffers == NULL)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        skel = SPA_MEMBER(impl->buffers, sizeof(struct spa_buffer *) * blocks, void);
 | 
					        skel = SPA_MEMBER(impl->buffers, sizeof(struct spa_buffer *) * blocks, void);
 | 
				
			||||||
	data_size = info.meta_size + info.chunk_size + info.data_size;
 | 
						data_size = info.meta_size + info.chunk_size + info.data_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl->mem) {
 | 
				
			||||||
 | 
							pw_memblock_free(impl->mem);
 | 
				
			||||||
 | 
							impl->mem = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
 | 
						if ((res = pw_memblock_alloc(PW_MEMBLOCK_FLAG_WITH_FD |
 | 
				
			||||||
				     PW_MEMBLOCK_FLAG_MAP_READWRITE |
 | 
									     PW_MEMBLOCK_FLAG_MAP_READWRITE |
 | 
				
			||||||
				     PW_MEMBLOCK_FLAG_SEAL, blocks * data_size,
 | 
									     PW_MEMBLOCK_FLAG_SEAL, blocks * data_size,
 | 
				
			||||||
| 
						 | 
					@ -800,18 +806,32 @@ static void client_node_initialized(void *data)
 | 
				
			||||||
	pw_node_set_active(impl->this.node, true);
 | 
						pw_node_set_active(impl->this.node, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void cleanup(struct impl *impl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (impl->use_converter) {
 | 
				
			||||||
 | 
							if (impl->adapter)
 | 
				
			||||||
 | 
								pw_unload_spa_interface(impl->adapter);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl->buffers)
 | 
				
			||||||
 | 
							free(impl->buffers);
 | 
				
			||||||
 | 
						if (impl->mem) {
 | 
				
			||||||
 | 
							pw_memblock_free(impl->mem);
 | 
				
			||||||
 | 
							impl->mem = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(impl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void client_node_destroy(void *data)
 | 
					static void client_node_destroy(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_log_debug("client-stream %p: destroy", &impl->this);
 | 
						pw_log_debug("client-stream %p: destroy", &impl->this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&impl->client_node_listener);
 | 
						spa_hook_remove(&impl->client_node_listener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&impl->node_listener);
 | 
						spa_hook_remove(&impl->node_listener);
 | 
				
			||||||
	pw_node_destroy(impl->this.node);
 | 
						pw_node_destroy(impl->this.node);
 | 
				
			||||||
 | 
						cleanup(impl);
 | 
				
			||||||
	free(impl);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void client_node_async_complete(void *data, uint32_t seq, int res)
 | 
					static void client_node_async_complete(void *data, uint32_t seq, int res)
 | 
				
			||||||
| 
						 | 
					@ -847,8 +867,7 @@ static void node_destroy(void *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&impl->client_node_listener);
 | 
						spa_hook_remove(&impl->client_node_listener);
 | 
				
			||||||
	pw_client_node_destroy(impl->client_node);
 | 
						pw_client_node_destroy(impl->client_node);
 | 
				
			||||||
 | 
						cleanup(impl);
 | 
				
			||||||
	free(impl);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct pw_node_events node_events = {
 | 
					static const struct pw_node_events node_events = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -710,8 +710,10 @@ static void destroy_server(struct pw_protocol_server *server)
 | 
				
			||||||
	spa_list_for_each_safe(client, tmp, &server->client_list, protocol_link)
 | 
						spa_list_for_each_safe(client, tmp, &server->client_list, protocol_link)
 | 
				
			||||||
		pw_client_destroy(client);
 | 
							pw_client_destroy(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (s->source)
 | 
						if (s->source) {
 | 
				
			||||||
 | 
							spa_hook_remove(&s->hook);
 | 
				
			||||||
		pw_loop_destroy_source(s->loop, s->source);
 | 
							pw_loop_destroy_source(s->loop, s->source);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (s->addr.sun_path[0])
 | 
						if (s->addr.sun_path[0])
 | 
				
			||||||
		unlink(s->addr.sun_path);
 | 
							unlink(s->addr.sun_path);
 | 
				
			||||||
	if (s->lock_addr[0])
 | 
						if (s->lock_addr[0])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -377,12 +377,36 @@ int pw_rtkit_make_high_priority(struct pw_rtkit_bus *connection, pid_t thread, i
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int do_remove_source(struct spa_loop *loop,
 | 
				
			||||||
 | 
								    bool async,
 | 
				
			||||||
 | 
								    uint32_t seq,
 | 
				
			||||||
 | 
								    const void *data,
 | 
				
			||||||
 | 
								    size_t size,
 | 
				
			||||||
 | 
								    void *user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct spa_source *source = user_data;
 | 
				
			||||||
 | 
						spa_loop_remove_source(loop, source);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void module_destroy(void *data)
 | 
					static void module_destroy(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_hook_remove(&impl->module_listener);
 | 
						spa_hook_remove(&impl->module_listener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl->source.fd != -1) {
 | 
				
			||||||
 | 
							spa_loop_invoke(impl->loop,
 | 
				
			||||||
 | 
									do_remove_source,
 | 
				
			||||||
 | 
									SPA_ID_INVALID,
 | 
				
			||||||
 | 
									NULL,
 | 
				
			||||||
 | 
									0,
 | 
				
			||||||
 | 
									true,
 | 
				
			||||||
 | 
									&impl->source);
 | 
				
			||||||
 | 
							close(impl->source.fd);
 | 
				
			||||||
 | 
							impl->source.fd = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->properties)
 | 
						if (impl->properties)
 | 
				
			||||||
		pw_properties_free(impl->properties);
 | 
							pw_properties_free(impl->properties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -448,6 +472,7 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie
 | 
				
			||||||
	struct spa_loop *loop;
 | 
						struct spa_loop *loop;
 | 
				
			||||||
	const struct spa_support *support;
 | 
						const struct spa_support *support;
 | 
				
			||||||
	uint32_t n_support;
 | 
						uint32_t n_support;
 | 
				
			||||||
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	support = pw_core_get_support(core, &n_support);
 | 
						support = pw_core_get_support(core, &n_support);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -471,11 +496,21 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie
 | 
				
			||||||
	impl->source.data = impl;
 | 
						impl->source.data = impl;
 | 
				
			||||||
	impl->source.fd = eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
						impl->source.fd = eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
				
			||||||
	impl->source.mask = SPA_IO_IN;
 | 
						impl->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
						if (impl->source.fd == -1) {
 | 
				
			||||||
 | 
							res = -errno;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_loop_add_source(impl->loop, &impl->source);
 | 
						spa_loop_add_source(impl->loop, &impl->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_module_add_listener(module, &impl->module_listener, &module_events, impl);
 | 
						pw_module_add_listener(module, &impl->module_listener, &module_events, impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      error:
 | 
				
			||||||
 | 
						free(impl);
 | 
				
			||||||
 | 
						return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pipewire__module_init(struct pw_module *module, const char *args)
 | 
					int pipewire__module_init(struct pw_module *module, const char *args)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,53 +34,130 @@
 | 
				
			||||||
#include "pipewire/pipewire.h"
 | 
					#include "pipewire/pipewire.h"
 | 
				
			||||||
#include "pipewire/private.h"
 | 
					#include "pipewire/private.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char **categories = NULL;
 | 
					#define MAX_SUPPORT	32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct plugin_info {
 | 
					struct plugin {
 | 
				
			||||||
 | 
						int ref;
 | 
				
			||||||
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
						char *filename;
 | 
				
			||||||
	void *hnd;
 | 
						void *hnd;
 | 
				
			||||||
	spa_handle_factory_enum_func_t enum_func;
 | 
						spa_handle_factory_enum_func_t enum_func;
 | 
				
			||||||
	struct spa_support support[16];
 | 
						struct spa_list handles;
 | 
				
			||||||
	uint32_t n_support;
 | 
					};
 | 
				
			||||||
} support_info;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					struct handle {
 | 
				
			||||||
open_plugin(const char *path,
 | 
						int ref;
 | 
				
			||||||
	    const char *lib,
 | 
						struct spa_list link;
 | 
				
			||||||
	    struct plugin_info *info)
 | 
						struct plugin *plugin;
 | 
				
			||||||
 | 
						const char *factory_name;
 | 
				
			||||||
 | 
						struct spa_handle *handle;
 | 
				
			||||||
 | 
						struct spa_list interfaces;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct interface {
 | 
				
			||||||
 | 
						int ref;
 | 
				
			||||||
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
						struct handle *handle;
 | 
				
			||||||
 | 
						const char *type;
 | 
				
			||||||
 | 
						void *iface;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct registry {
 | 
				
			||||||
 | 
						struct spa_list plugins;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct support {
 | 
				
			||||||
 | 
						char **categories;
 | 
				
			||||||
 | 
						const char *plugin_dir;
 | 
				
			||||||
 | 
						struct plugin *support_plugin;
 | 
				
			||||||
 | 
						struct spa_support support[MAX_SUPPORT];
 | 
				
			||||||
 | 
						uint32_t n_support;
 | 
				
			||||||
 | 
						struct registry *registry;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct registry global_registry;
 | 
				
			||||||
 | 
					static struct support global_support;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct plugin *
 | 
				
			||||||
 | 
					find_plugin(struct registry *registry, const char *filename)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct plugin *p;
 | 
				
			||||||
 | 
						spa_list_for_each(p, ®istry->plugins, link) {
 | 
				
			||||||
 | 
							if (!strcmp(p->filename, filename))
 | 
				
			||||||
 | 
								return p;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct plugin *
 | 
				
			||||||
 | 
					open_plugin(struct registry *registry,
 | 
				
			||||||
 | 
						    const char *path,
 | 
				
			||||||
 | 
						    const char *lib)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct plugin *plugin;
 | 
				
			||||||
	char *filename;
 | 
						char *filename;
 | 
				
			||||||
 | 
						void *hnd;
 | 
				
			||||||
 | 
						spa_handle_factory_enum_func_t enum_func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (asprintf(&filename, "%s/%s.so", path, lib) < 0)
 | 
					        if (asprintf(&filename, "%s/%s.so", path, lib) < 0)
 | 
				
			||||||
		goto no_filename;
 | 
							goto no_filename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((info->hnd = dlopen(filename, RTLD_NOW)) == NULL) {
 | 
						if ((plugin = find_plugin(registry, filename)) != NULL) {
 | 
				
			||||||
 | 
							free(filename);
 | 
				
			||||||
 | 
							plugin->ref++;
 | 
				
			||||||
 | 
							return plugin;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((hnd = dlopen(filename, RTLD_NOW)) == NULL) {
 | 
				
			||||||
                fprintf(stderr, "can't load %s: %s\n", filename, dlerror());
 | 
					                fprintf(stderr, "can't load %s: %s\n", filename, dlerror());
 | 
				
			||||||
                goto open_failed;
 | 
					                goto open_failed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if ((info->enum_func = dlsym(info->hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
 | 
					        if ((enum_func = dlsym(hnd, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)) == NULL) {
 | 
				
			||||||
                fprintf(stderr, "can't find enum function\n");
 | 
					                fprintf(stderr, "can't find enum function\n");
 | 
				
			||||||
                goto no_symbol;
 | 
					                goto no_symbol;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
	free(filename);
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      no_filename:
 | 
						if ((plugin = calloc(1, sizeof(struct plugin))) == NULL)
 | 
				
			||||||
	return false;
 | 
							goto alloc_failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						plugin->ref = 1;
 | 
				
			||||||
 | 
						plugin->filename = filename;
 | 
				
			||||||
 | 
						plugin->hnd = hnd;
 | 
				
			||||||
 | 
						plugin->enum_func = enum_func;
 | 
				
			||||||
 | 
						spa_list_init(&plugin->handles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_append(®istry->plugins, &plugin->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      alloc_failed:
 | 
				
			||||||
      no_symbol:
 | 
					      no_symbol:
 | 
				
			||||||
	dlclose(info->hnd);
 | 
						dlclose(hnd);
 | 
				
			||||||
      open_failed:
 | 
					      open_failed:
 | 
				
			||||||
        free(filename);
 | 
					        free(filename);
 | 
				
			||||||
	return false;
 | 
					      no_filename:
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct spa_handle_factory *get_factory(struct plugin_info *info, const char *factory_name)
 | 
					static void
 | 
				
			||||||
 | 
					unref_plugin(struct plugin *plugin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (--plugin->ref == 0) {
 | 
				
			||||||
 | 
							spa_list_remove(&plugin->link);
 | 
				
			||||||
 | 
							dlclose(plugin->hnd);
 | 
				
			||||||
 | 
							free(plugin->filename);
 | 
				
			||||||
 | 
							free(plugin);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct spa_handle_factory *find_factory(struct plugin *plugin, const char *factory_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	uint32_t index;
 | 
						uint32_t index;
 | 
				
			||||||
        const struct spa_handle_factory *factory;
 | 
					        const struct spa_handle_factory *factory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (index = 0;;) {
 | 
					        for (index = 0;;) {
 | 
				
			||||||
                if ((res = info->enum_func(&factory, &index)) <= 0) {
 | 
					                if ((res = plugin->enum_func(&factory, &index)) <= 0) {
 | 
				
			||||||
                        if (res != 0)
 | 
					                        if (res != 0)
 | 
				
			||||||
                                fprintf(stderr, "can't enumerate factories: %s\n", spa_strerror(res));
 | 
					                                fprintf(stderr, "can't enumerate factories: %s\n", spa_strerror(res));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
| 
						 | 
					@ -91,47 +168,121 @@ static const struct spa_handle_factory *get_factory(struct plugin_info *info, co
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *
 | 
					static struct handle *
 | 
				
			||||||
load_interface(struct plugin_info *info,
 | 
					load_handle(struct plugin *plugin,
 | 
				
			||||||
	       const char *factory_name,
 | 
						    const char *factory_name,
 | 
				
			||||||
	       const char *type)
 | 
						    uint32_t n_support,
 | 
				
			||||||
 | 
						    struct spa_support support[n_support])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
        int res;
 | 
					        int res;
 | 
				
			||||||
        struct spa_handle *handle;
 | 
					        struct handle *handle;
 | 
				
			||||||
        uint32_t type_id;
 | 
					        struct spa_handle *hnd;
 | 
				
			||||||
        const struct spa_handle_factory *factory;
 | 
					        const struct spa_handle_factory *factory;
 | 
				
			||||||
        void *iface;
 | 
					 | 
				
			||||||
	struct spa_type_map *map = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	factory = get_factory(info, factory_name);
 | 
						factory = find_factory(plugin, factory_name);
 | 
				
			||||||
	if (factory == NULL)
 | 
						if (factory == NULL)
 | 
				
			||||||
		goto not_found;
 | 
							goto not_found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        handle = calloc(1, spa_handle_factory_get_size(factory, NULL));
 | 
						hnd = calloc(1, spa_handle_factory_get_size(factory, NULL));
 | 
				
			||||||
 | 
						if (hnd == NULL)
 | 
				
			||||||
 | 
							goto alloc_failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((res = spa_handle_factory_init(factory,
 | 
					        if ((res = spa_handle_factory_init(factory,
 | 
				
			||||||
                                           handle, NULL, info->support, info->n_support)) < 0) {
 | 
					                                           hnd, NULL,
 | 
				
			||||||
 | 
										   support, n_support)) < 0) {
 | 
				
			||||||
                fprintf(stderr, "can't make factory instance: %d\n", res);
 | 
					                fprintf(stderr, "can't make factory instance: %d\n", res);
 | 
				
			||||||
                goto init_failed;
 | 
					                goto init_failed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	map = pw_get_support_interface(SPA_TYPE__TypeMap);
 | 
						if ((handle = calloc(1, sizeof(struct handle))) == NULL)
 | 
				
			||||||
 | 
							goto handle_failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						handle->ref = 1;
 | 
				
			||||||
 | 
						handle->plugin = plugin;
 | 
				
			||||||
 | 
						handle->factory_name = factory_name;
 | 
				
			||||||
 | 
						handle->handle = hnd;
 | 
				
			||||||
 | 
						spa_list_init(&handle->interfaces);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_append(&plugin->handles, &handle->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      handle_failed:
 | 
				
			||||||
 | 
						spa_handle_clear(hnd);
 | 
				
			||||||
 | 
					      init_failed:
 | 
				
			||||||
 | 
						free(hnd);
 | 
				
			||||||
 | 
					      alloc_failed:
 | 
				
			||||||
 | 
					      not_found:
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void unref_handle(struct handle *handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (--handle->ref == 0) {
 | 
				
			||||||
 | 
							spa_list_remove(&handle->link);
 | 
				
			||||||
 | 
							spa_handle_clear(handle->handle);
 | 
				
			||||||
 | 
							free(handle->handle);
 | 
				
			||||||
 | 
							unref_plugin(handle->plugin);
 | 
				
			||||||
 | 
							free(handle);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct interface *
 | 
				
			||||||
 | 
					load_interface(struct plugin *plugin,
 | 
				
			||||||
 | 
						       const char *factory_name,
 | 
				
			||||||
 | 
						       const char *type,
 | 
				
			||||||
 | 
						       uint32_t n_support,
 | 
				
			||||||
 | 
						       struct spa_support support[n_support])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        int res;
 | 
				
			||||||
 | 
					        struct handle *handle;
 | 
				
			||||||
 | 
					        uint32_t type_id;
 | 
				
			||||||
 | 
					        void *ptr;
 | 
				
			||||||
 | 
						struct spa_type_map *map = NULL;
 | 
				
			||||||
 | 
						struct interface *iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        handle = load_handle(plugin, factory_name, n_support, support);
 | 
				
			||||||
 | 
						if (handle == NULL)
 | 
				
			||||||
 | 
							goto not_found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						map = spa_support_find(support, n_support, SPA_TYPE__TypeMap);
 | 
				
			||||||
	type_id = map ? spa_type_map_get_id(map, type) : 0;
 | 
						type_id = map ? spa_type_map_get_id(map, type) : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((res = spa_handle_get_interface(handle, type_id, &iface)) < 0) {
 | 
					        if ((res = spa_handle_get_interface(handle->handle, type_id, &ptr)) < 0) {
 | 
				
			||||||
                fprintf(stderr, "can't get %s interface %d\n", type, res);
 | 
					                fprintf(stderr, "can't get %s interface %d\n", type, res);
 | 
				
			||||||
                goto interface_failed;
 | 
					                goto interface_failed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((iface = calloc(1, sizeof(struct interface))) == NULL)
 | 
				
			||||||
 | 
							goto alloc_failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iface->ref = 1;
 | 
				
			||||||
 | 
						iface->handle = handle;
 | 
				
			||||||
 | 
						iface->type = type;
 | 
				
			||||||
 | 
						iface->iface = ptr;
 | 
				
			||||||
 | 
						spa_list_append(&handle->interfaces, &iface->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return iface;
 | 
					        return iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      alloc_failed:
 | 
				
			||||||
      interface_failed:
 | 
					      interface_failed:
 | 
				
			||||||
	spa_handle_clear(handle);
 | 
						unref_handle(handle);
 | 
				
			||||||
      init_failed:
 | 
					 | 
				
			||||||
	free(handle);
 | 
						free(handle);
 | 
				
			||||||
      not_found:
 | 
					      not_found:
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void configure_debug(const char *str)
 | 
					static void
 | 
				
			||||||
 | 
					unref_interface(struct interface *iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (--iface->ref == 0) {
 | 
				
			||||||
 | 
							spa_list_remove(&iface->link);
 | 
				
			||||||
 | 
							unref_handle(iface->handle);
 | 
				
			||||||
 | 
							free(iface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void configure_debug(struct support *support, const char *str)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char **level;
 | 
						char **level;
 | 
				
			||||||
	int n_tokens;
 | 
						int n_tokens;
 | 
				
			||||||
| 
						 | 
					@ -141,7 +292,7 @@ static void configure_debug(const char *str)
 | 
				
			||||||
		pw_log_set_level(atoi(level[0]));
 | 
							pw_log_set_level(atoi(level[0]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (n_tokens > 1)
 | 
						if (n_tokens > 1)
 | 
				
			||||||
		categories = pw_split_strv(level[1], ",", INT_MAX, &n_tokens);
 | 
							support->categories = pw_split_strv(level[1], ",", INT_MAX, &n_tokens);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Get a support interface
 | 
					/** Get a support interface
 | 
				
			||||||
| 
						 | 
					@ -150,52 +301,80 @@ static void configure_debug(const char *str)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void *pw_get_support_interface(const char *type)
 | 
					void *pw_get_support_interface(const char *type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						return spa_support_find(global_support.support, global_support.n_support, type);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < support_info.n_support; i++) {
 | 
					 | 
				
			||||||
		if (strcmp(support_info.support->type, type) == 0)
 | 
					 | 
				
			||||||
			return support_info.support->data;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct spa_handle_factory *pw_get_support_factory(const char *factory_name)
 | 
					const struct spa_handle_factory *pw_get_support_factory(const char *factory_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return get_factory(&support_info, factory_name);
 | 
						struct plugin *plugin = global_support.support_plugin;
 | 
				
			||||||
 | 
						return find_factory(plugin, factory_name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct spa_support *pw_get_support(uint32_t *n_support)
 | 
					const struct spa_support *pw_get_support(uint32_t *n_support)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	*n_support = support_info.n_support;
 | 
						*n_support = global_support.n_support;
 | 
				
			||||||
	return support_info.support;
 | 
						return global_support.support;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *pw_load_spa_interface(const char *lib, const char *factory_name, const char *type,
 | 
					void *pw_load_spa_interface(const char *lib, const char *factory_name, const char *type,
 | 
				
			||||||
			    struct spa_support *support, uint32_t n_support)
 | 
								    struct spa_support *support, uint32_t n_support)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct plugin_info extra_support_info;
 | 
						struct support *sup = &global_support;
 | 
				
			||||||
	const char *str;
 | 
						struct spa_support extra_support[MAX_SUPPORT];
 | 
				
			||||||
 | 
						uint32_t extra_n_support;
 | 
				
			||||||
 | 
						struct plugin *plugin;
 | 
				
			||||||
 | 
						struct interface *iface;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extra_support_info.n_support = support_info.n_support;
 | 
						extra_n_support = sup->n_support;
 | 
				
			||||||
	memcpy(extra_support_info.support, support_info.support,
 | 
						memcpy(extra_support, sup->support,
 | 
				
			||||||
			sizeof(struct spa_support) * extra_support_info.n_support);
 | 
								sizeof(struct spa_support) * sup->n_support);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < n_support; i++) {
 | 
						for (i = 0; i < n_support; i++) {
 | 
				
			||||||
		extra_support_info.support[extra_support_info.n_support++] =
 | 
							extra_support[extra_n_support++] =
 | 
				
			||||||
			SPA_SUPPORT_INIT(support[i].type, support[i].data);
 | 
								SPA_SUPPORT_INIT(support[i].type, support[i].data);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ((str = getenv("SPA_PLUGIN_DIR")) == NULL)
 | 
					 | 
				
			||||||
		str = PLUGINDIR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_log_debug("load \"%s\", \"%s\"", lib, factory_name);
 | 
						pw_log_debug("load \"%s\", \"%s\"", lib, factory_name);
 | 
				
			||||||
 | 
						if ((plugin = open_plugin(sup->registry, sup->plugin_dir, lib)) == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (open_plugin(str, lib, &extra_support_info))
 | 
						if ((iface = load_interface(plugin, factory_name,
 | 
				
			||||||
		return load_interface(&extra_support_info, factory_name, type);
 | 
										type, extra_n_support, extra_support)) == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return iface->iface;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct interface *find_interface(void *iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct registry *registry = global_support.registry;
 | 
				
			||||||
 | 
						struct plugin *p;
 | 
				
			||||||
 | 
						struct handle *h;
 | 
				
			||||||
 | 
						struct interface *i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_for_each(p, ®istry->plugins, link) {
 | 
				
			||||||
 | 
							spa_list_for_each(h, &p->handles, link) {
 | 
				
			||||||
 | 
								spa_list_for_each(i, &h->interfaces, link) {
 | 
				
			||||||
 | 
									if (i->iface == iface)
 | 
				
			||||||
 | 
										return i;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pw_unload_spa_interface(void *iface)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct interface *i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((i = find_interface(iface)) == NULL)
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unref_interface(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *pw_get_spa_dbus(struct pw_loop *loop)
 | 
					void *pw_get_spa_dbus(struct pw_loop *loop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spa_support support = SPA_SUPPORT_INIT(SPA_TYPE__LoopUtils, loop->utils);
 | 
						struct spa_support support = SPA_SUPPORT_INIT(SPA_TYPE__LoopUtils, loop->utils);
 | 
				
			||||||
| 
						 | 
					@ -219,28 +398,43 @@ void *pw_get_spa_dbus(struct pw_loop *loop)
 | 
				
			||||||
void pw_init(int *argc, char **argv[])
 | 
					void pw_init(int *argc, char **argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
	void *iface;
 | 
						struct interface *iface;
 | 
				
			||||||
	struct plugin_info *info = &support_info;
 | 
						struct support *support = &global_support;
 | 
				
			||||||
 | 
						struct plugin *plugin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = getenv("PIPEWIRE_DEBUG")))
 | 
						if ((str = getenv("PIPEWIRE_DEBUG")))
 | 
				
			||||||
		configure_debug(str);
 | 
							configure_debug(support, str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = getenv("SPA_PLUGIN_DIR")) == NULL)
 | 
						if ((str = getenv("SPA_PLUGIN_DIR")) == NULL)
 | 
				
			||||||
		str = PLUGINDIR;
 | 
							str = PLUGINDIR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (support_info.n_support > 0)
 | 
						support->plugin_dir = str;
 | 
				
			||||||
 | 
						spa_list_init(&global_registry.plugins);
 | 
				
			||||||
 | 
						support->registry = &global_registry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (support->n_support > 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (open_plugin(str, "support/libspa-support", info)) {
 | 
						plugin = open_plugin(support->registry, support->plugin_dir, "support/libspa-support");
 | 
				
			||||||
		iface = load_interface(info, "mapper", SPA_TYPE__TypeMap);
 | 
						if (plugin == NULL) {
 | 
				
			||||||
		if (iface != NULL)
 | 
							fprintf(stderr, "can't open support library");
 | 
				
			||||||
			info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface);
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		iface = load_interface(info, "logger", SPA_TYPE__Log);
 | 
						support->support_plugin = plugin;
 | 
				
			||||||
		if (iface != NULL) {
 | 
					
 | 
				
			||||||
			info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface);
 | 
						iface = load_interface(plugin, "mapper", SPA_TYPE__TypeMap,
 | 
				
			||||||
			pw_log_set(iface);
 | 
								support->n_support, support->support);
 | 
				
			||||||
		}
 | 
						if (iface != NULL)
 | 
				
			||||||
 | 
							support->support[support->n_support++] =
 | 
				
			||||||
 | 
								SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface->iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						iface = load_interface(plugin, "logger", SPA_TYPE__Log,
 | 
				
			||||||
 | 
								support->n_support, support->support);
 | 
				
			||||||
 | 
						if (iface != NULL) {
 | 
				
			||||||
 | 
							support->support[support->n_support++] =
 | 
				
			||||||
 | 
								SPA_SUPPORT_INIT(SPA_TYPE__Log, iface->iface);
 | 
				
			||||||
 | 
							pw_log_set(iface->iface);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,11 +452,11 @@ bool pw_debug_is_category_enabled(const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (categories == NULL)
 | 
						if (global_support.categories == NULL)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; categories[i]; i++) {
 | 
						for (i = 0; global_support.categories[i]; i++) {
 | 
				
			||||||
		if (strcmp (categories[i], name) == 0)
 | 
							if (strcmp(global_support.categories[i], name) == 0)
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,6 +134,7 @@ pw_get_support_interface(const char *type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *pw_load_spa_interface(const char *lib, const char *factory_name, const char *type,
 | 
					void *pw_load_spa_interface(const char *lib, const char *factory_name, const char *type,
 | 
				
			||||||
		struct spa_support *support, uint32_t n_support);
 | 
							struct spa_support *support, uint32_t n_support);
 | 
				
			||||||
 | 
					int pw_unload_spa_interface(void *iface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void *pw_get_spa_dbus(struct pw_loop *loop);
 | 
					void *pw_get_spa_dbus(struct pw_loop *loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue