pipewire: only load spa_handle

Only provide a method to load a spa_handle, getting the interface
from that is easy and we only use refcounting on the handle.
This commit is contained in:
Wim Taymans 2019-05-20 09:49:39 +02:00
parent da9f0ed160
commit b195a25636
5 changed files with 86 additions and 128 deletions

View file

@ -91,6 +91,7 @@ struct impl {
enum spa_direction direction; enum spa_direction direction;
struct spa_node *cnode; struct spa_node *cnode;
struct spa_handle *handle;
struct spa_node *adapter; struct spa_node *adapter;
struct spa_hook adapter_listener; struct spa_hook adapter_listener;
struct spa_node *adapter_mix; struct spa_node *adapter_mix;
@ -1055,6 +1056,7 @@ static void client_node_initialized(void *data)
media_subtype == SPA_MEDIA_SUBTYPE_raw) { media_subtype == SPA_MEDIA_SUBTYPE_raw) {
struct spa_dict_item items[2]; struct spa_dict_item items[2];
const char *mode; const char *mode;
void *iface;
if (impl->direction == SPA_DIRECTION_OUTPUT) if (impl->direction == SPA_DIRECTION_OUTPUT)
mode = "split"; mode = "split";
@ -1064,13 +1066,18 @@ static void client_node_initialized(void *data)
items[0] = SPA_DICT_ITEM_INIT("factory.mode", mode); items[0] = SPA_DICT_ITEM_INIT("factory.mode", mode);
items[1] = SPA_DICT_ITEM_INIT("resample.peaks", monitor ? "1" : "0"); items[1] = SPA_DICT_ITEM_INIT("resample.peaks", monitor ? "1" : "0");
if ((impl->adapter = pw_load_spa_interface("audioconvert/libspa-audioconvert",
if ((impl->handle = pw_load_spa_handle("audioconvert/libspa-audioconvert",
"audioconvert", "audioconvert",
SPA_TYPE_INTERFACE_Node,
&SPA_DICT_INIT(items, 2), &SPA_DICT_INIT(items, 2),
0, NULL)) == NULL) 0, NULL)) == NULL)
return; return;
if ((res = spa_handle_get_interface(impl->handle,
SPA_TYPE_INTERFACE_Node, &iface)) < 0)
return;
impl->adapter = iface;
impl->adapter_mix = impl->adapter; impl->adapter_mix = impl->adapter;
impl->adapter_mix_port = 0; impl->adapter_mix_port = 0;
impl->use_converter = true; impl->use_converter = true;
@ -1118,8 +1125,8 @@ static void cleanup(struct impl *impl)
{ {
pw_log_debug("client-stream %p: cleanup", &impl->this); pw_log_debug("client-stream %p: cleanup", &impl->this);
if (impl->use_converter) { if (impl->use_converter) {
if (impl->adapter) if (impl->handle)
pw_unload_spa_interface(impl->adapter); pw_unload_spa_handle(impl->handle);
} }
free(impl->buffers); free(impl->buffers);

View file

@ -68,12 +68,8 @@ static void device_destroy(void *data)
pw_log_debug("spa-device %p: free", device); pw_log_debug("spa-device %p: free", device);
spa_hook_remove(&impl->device_listener); spa_hook_remove(&impl->device_listener);
if (impl->unload) if (impl->handle)
pw_unload_spa_interface(impl->unload); pw_unload_spa_handle(impl->handle);
if (impl->handle) {
spa_handle_clear(impl->handle);
free(impl->handle);
}
free(impl->lib); free(impl->lib);
free(impl->factory_name); free(impl->factory_name);
} }
@ -106,6 +102,7 @@ pw_spa_device_new(struct pw_core *core,
impl->owner = owner; impl->owner = owner;
impl->parent = parent; impl->parent = parent;
impl->device = device; impl->device = device;
impl->handle = handle;
impl->flags = flags; impl->flags = flags;
if (user_data_size > 0) if (user_data_size > 0)
@ -138,22 +135,28 @@ struct pw_device *pw_spa_device_load(struct pw_core *core,
{ {
struct pw_device *this; struct pw_device *this;
struct impl *impl; struct impl *impl;
struct spa_device *device; struct spa_handle *handle;
const struct spa_support *support; const struct spa_support *support;
uint32_t n_support; uint32_t n_support;
void *iface;
int res;
support = pw_core_get_support(core, &n_support); support = pw_core_get_support(core, &n_support);
device = pw_load_spa_interface(lib, factory_name, SPA_TYPE_INTERFACE_Device, handle = pw_load_spa_handle(lib, factory_name,
properties ? &properties->dict : NULL, n_support, support); properties ? &properties->dict : NULL, n_support, support);
if (device == NULL) if (handle == NULL)
goto open_failed; goto open_failed;
if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) {
pw_log_error("can't get device interface %d\n", res);
goto open_failed;
}
this = pw_spa_device_new(core, owner, parent, name, flags, this = pw_spa_device_new(core, owner, parent, name, flags,
device, NULL, properties, user_data_size); iface, handle, properties, user_data_size);
impl = this->user_data; impl = this->user_data;
impl->unload = device;
impl->lib = strdup(lib); impl->lib = strdup(lib);
impl->factory_name = strdup(factory_name); impl->factory_name = strdup(factory_name);

View file

@ -48,7 +48,7 @@
/** \cond */ /** \cond */
struct impl { struct impl {
struct pw_core this; struct pw_core this;
void *dbus_iface; struct spa_handle *dbus_handle;
}; };
@ -441,6 +441,8 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop,
struct impl *impl; struct impl *impl;
struct pw_core *this; struct pw_core *this;
const char *name; const char *name;
void *dbus_iface = NULL;
int res;
impl = calloc(1, sizeof(struct impl) + user_data_size); impl = calloc(1, sizeof(struct impl) + user_data_size);
if (impl == NULL) if (impl == NULL)
@ -473,9 +475,14 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop,
this->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_MainLoop, this->main_loop->loop); this->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_MainLoop, this->main_loop->loop);
this->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_LoopUtils, this->main_loop->utils); this->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_LoopUtils, this->main_loop->utils);
this->support[3] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, pw_log_get()); this->support[3] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, pw_log_get());
impl->dbus_iface = pw_load_spa_interface("support/libspa-dbus",
"dbus", SPA_TYPE_INTERFACE_DBus, NULL, 4, this->support); impl->dbus_handle = pw_load_spa_handle("support/libspa-dbus", "dbus", NULL, 4, this->support);
this->support[4] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DBus, impl->dbus_iface); if (impl->dbus_handle) {
if ((res = spa_handle_get_interface(impl->dbus_handle,
SPA_TYPE_INTERFACE_DBus, &dbus_iface)) < 0)
pw_log_warn("can't load dbus interface: %s", spa_strerror(res));
}
this->support[4] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DBus, dbus_iface);
this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_CPU, this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_CPU,
pw_get_support_interface(SPA_TYPE_INTERFACE_CPU)); pw_get_support_interface(SPA_TYPE_INTERFACE_CPU));
this->n_support = 6; this->n_support = 6;
@ -586,7 +593,8 @@ void pw_core_destroy(struct pw_core *core)
pw_map_clear(&core->globals); pw_map_clear(&core->globals);
pw_unload_spa_interface(impl->dbus_iface); if (impl->dbus_handle)
pw_unload_spa_handle(impl->dbus_handle);
pw_log_debug("core %p: free", core); pw_log_debug("core %p: free", core);
free(core); free(core);

View file

@ -54,17 +54,8 @@ struct handle {
struct spa_list link; struct spa_list link;
struct plugin *plugin; struct plugin *plugin;
const char *factory_name; const char *factory_name;
struct spa_handle *handle;
struct spa_list interfaces;
int ref;
};
struct interface {
struct spa_list link;
struct handle *handle;
void *iface;
uint32_t type;
int ref; int ref;
struct spa_handle handle;
}; };
struct registry { struct registry {
@ -182,41 +173,32 @@ load_handle(struct plugin *plugin,
{ {
int res; int res;
struct handle *handle; struct handle *handle;
struct spa_handle *hnd;
const struct spa_handle_factory *factory; const struct spa_handle_factory *factory;
factory = find_factory(plugin, factory_name); factory = find_factory(plugin, factory_name);
if (factory == NULL) if (factory == NULL)
goto not_found; goto not_found;
hnd = calloc(1, spa_handle_factory_get_size(factory, NULL)); handle = calloc(1, sizeof(struct handle) + spa_handle_factory_get_size(factory, info));
if (hnd == NULL) if (handle == NULL)
goto alloc_failed; goto alloc_failed;
if ((res = spa_handle_factory_init(factory, if ((res = spa_handle_factory_init(factory,
hnd, info, &handle->handle, info,
support, n_support)) < 0) { support, n_support)) < 0) {
fprintf(stderr, "can't make factory instance %s: %d\n", factory_name, res); fprintf(stderr, "can't make factory instance %s: %d\n", factory_name, res);
goto init_failed; goto init_failed;
} }
if ((handle = calloc(1, sizeof(struct handle))) == NULL)
goto handle_failed;
handle->ref = 1; handle->ref = 1;
handle->plugin = plugin; handle->plugin = plugin;
handle->factory_name = factory_name; handle->factory_name = factory_name;
handle->handle = hnd;
spa_list_init(&handle->interfaces);
spa_list_append(&plugin->handles, &handle->link); spa_list_append(&plugin->handles, &handle->link);
return handle; return handle;
handle_failed:
spa_handle_clear(hnd);
init_failed: init_failed:
free(hnd); free(handle);
alloc_failed: alloc_failed:
not_found: not_found:
return NULL; return NULL;
@ -226,64 +208,12 @@ static void unref_handle(struct handle *handle)
{ {
if (--handle->ref == 0) { if (--handle->ref == 0) {
spa_list_remove(&handle->link); spa_list_remove(&handle->link);
spa_handle_clear(handle->handle); spa_handle_clear(&handle->handle);
free(handle->handle);
unref_plugin(handle->plugin); unref_plugin(handle->plugin);
free(handle); free(handle);
} }
} }
static struct interface *
load_interface(struct plugin *plugin,
const char *factory_name,
uint32_t type_id,
const struct spa_dict *info,
uint32_t n_support,
struct spa_support support[n_support])
{
int res;
struct handle *handle;
void *ptr;
struct interface *iface;
handle = load_handle(plugin, factory_name, info, n_support, support);
if (handle == NULL)
goto not_found;
if ((res = spa_handle_get_interface(handle->handle, type_id, &ptr)) < 0) {
fprintf(stderr, "can't get %d interface %d\n", type_id, res);
goto interface_failed;
}
if ((iface = calloc(1, sizeof(struct interface))) == NULL)
goto alloc_failed;
iface->ref = 1;
iface->handle = handle;
iface->type = type_id;
iface->iface = ptr;
spa_list_append(&handle->interfaces, &iface->link);
return iface;
alloc_failed:
interface_failed:
unref_handle(handle);
free(handle);
not_found:
return NULL;
}
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) static void configure_debug(struct support *support, const char *str)
{ {
char **level; char **level;
@ -327,16 +257,17 @@ const struct spa_support *pw_get_support(uint32_t *n_support)
} }
SPA_EXPORT SPA_EXPORT
void *pw_load_spa_interface(const char *lib, const char *factory_name, uint32_t type, struct spa_handle *pw_load_spa_handle(const char *lib,
const struct spa_dict *info, const char *factory_name,
uint32_t n_support, const struct spa_dict *info,
const struct spa_support support[]) uint32_t n_support,
const struct spa_support support[])
{ {
struct support *sup = &global_support; struct support *sup = &global_support;
struct spa_support extra_support[MAX_SUPPORT]; struct spa_support extra_support[MAX_SUPPORT];
uint32_t extra_n_support; uint32_t extra_n_support;
struct plugin *plugin; struct plugin *plugin;
struct interface *iface; struct handle *handle;
uint32_t i; uint32_t i;
extra_n_support = sup->n_support; extra_n_support = sup->n_support;
@ -353,40 +284,37 @@ void *pw_load_spa_interface(const char *lib, const char *factory_name, uint32_t
return NULL; return NULL;
} }
if ((iface = load_interface(plugin, factory_name, type, info, handle = load_handle(plugin, factory_name, info, extra_n_support, extra_support);
extra_n_support, extra_support)) == NULL) if (handle == NULL)
return NULL; return NULL;
return iface->iface; return &handle->handle;
} }
static struct interface *find_interface(void *iface) static struct handle *find_handle(struct spa_handle *handle)
{ {
struct registry *registry = global_support.registry; struct registry *registry = global_support.registry;
struct plugin *p; struct plugin *p;
struct handle *h; struct handle *h;
struct interface *i;
spa_list_for_each(p, &registry->plugins, link) { spa_list_for_each(p, &registry->plugins, link) {
spa_list_for_each(h, &p->handles, link) { spa_list_for_each(h, &p->handles, link) {
spa_list_for_each(i, &h->interfaces, link) { if (&h->handle == handle)
if (i->iface == iface) return h;
return i;
}
} }
} }
return NULL; return NULL;
} }
SPA_EXPORT SPA_EXPORT
int pw_unload_spa_interface(void *iface) int pw_unload_spa_handle(struct spa_handle *handle)
{ {
struct interface *i; struct handle *h;
if ((i = find_interface(iface)) == NULL) if ((h = find_handle(handle)) == NULL)
return -ENOENT; return -ENOENT;
unref_interface(i); unref_handle(h);
return 0; return 0;
} }
@ -407,11 +335,13 @@ SPA_EXPORT
void pw_init(int *argc, char **argv[]) void pw_init(int *argc, char **argv[])
{ {
const char *str; const char *str;
struct interface *iface; struct handle *handle;
void *iface;
struct support *support = &global_support; struct support *support = &global_support;
struct plugin *plugin; struct plugin *plugin;
struct spa_dict info; struct spa_dict info;
struct spa_dict_item items[1]; struct spa_dict_item items[1];
int res = 0;
if ((str = getenv("PIPEWIRE_DEBUG"))) if ((str = getenv("PIPEWIRE_DEBUG")))
configure_debug(support, str); configure_debug(support, str);
@ -437,22 +367,31 @@ void pw_init(int *argc, char **argv[])
items[0] = SPA_DICT_ITEM_INIT("log.colors", "1"); items[0] = SPA_DICT_ITEM_INIT("log.colors", "1");
info = SPA_DICT_INIT(items, 1); info = SPA_DICT_INIT(items, 1);
iface = load_interface(plugin, "logger", SPA_TYPE_INTERFACE_Log, &info, handle = load_handle(plugin, "logger", &info, support->n_support, support->support);
support->n_support, support->support); if (handle == NULL ||
if (iface != NULL) { (res = spa_handle_get_interface(&handle->handle,
support->support[support->n_support++] = SPA_TYPE_INTERFACE_Log, &iface)) < 0) {
SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, iface->iface); fprintf(stderr, "can't get Log interface %d\n", res);
pw_log_set(iface->iface);
} }
iface = load_interface(plugin, "cpu", SPA_TYPE_INTERFACE_CPU, &info, else {
support->n_support, support->support); support->support[support->n_support++] =
if (iface != NULL) { SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_Log, iface);
struct spa_cpu *cpu = iface->iface; pw_log_set(iface);
}
handle = load_handle(plugin, "cpu", &info, support->n_support, support->support);
if (handle == NULL ||
(res = spa_handle_get_interface(&handle->handle,
SPA_TYPE_INTERFACE_CPU, &iface)) < 0) {
fprintf(stderr, "can't get CPU interface %d\n", res);
}
else {
struct spa_cpu *cpu = iface;
if ((str = getenv("PIPEWIRE_CPU"))) if ((str = getenv("PIPEWIRE_CPU")))
spa_cpu_force_flags(cpu, strtoul(str, NULL, 0)); spa_cpu_force_flags(cpu, strtoul(str, NULL, 0));
support->support[support->n_support++] = support->support[support->n_support++] =
SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_CPU, iface->iface); SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_CPU, iface);
} }
pw_log_info("version %s", pw_get_library_version()); pw_log_info("version %s", pw_get_library_version());
} }

View file

@ -139,12 +139,13 @@ pw_direction_reverse(enum pw_direction direction);
void * void *
pw_get_support_interface(uint32_t type); pw_get_support_interface(uint32_t type);
void *pw_load_spa_interface(const char *lib, const char *factory_name, uint32_t type, struct spa_handle *pw_load_spa_handle(const char *lib,
const char *factory_name,
const struct spa_dict *info, const struct spa_dict *info,
uint32_t n_support, uint32_t n_support,
const struct spa_support support[]); const struct spa_support support[]);
int pw_unload_spa_interface(void *iface); int pw_unload_spa_handle(struct spa_handle *handle);
const struct spa_handle_factory * const struct spa_handle_factory *
pw_get_support_factory(const char *factory_name); pw_get_support_factory(const char *factory_name);