mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
Use refcounting for async shutdown
fix some memory leaks
This commit is contained in:
parent
ee0aa6a2ac
commit
6d4db64767
21 changed files with 216 additions and 260 deletions
|
|
@ -42,8 +42,6 @@ pinos_node_state_as_string (PinosNodeState state)
|
|||
return "creating";
|
||||
case PINOS_NODE_STATE_SUSPENDED:
|
||||
return "suspended";
|
||||
case PINOS_NODE_STATE_INITIALIZING:
|
||||
return "initializing";
|
||||
case PINOS_NODE_STATE_IDLE:
|
||||
return "idle";
|
||||
case PINOS_NODE_STATE_RUNNING:
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ enum _PinosNodeState {
|
|||
PINOS_NODE_STATE_ERROR = -1,
|
||||
PINOS_NODE_STATE_CREATING = 0,
|
||||
PINOS_NODE_STATE_SUSPENDED = 1,
|
||||
PINOS_NODE_STATE_INITIALIZING = 2,
|
||||
PINOS_NODE_STATE_IDLE = 3,
|
||||
PINOS_NODE_STATE_RUNNING = 4,
|
||||
PINOS_NODE_STATE_IDLE = 2,
|
||||
PINOS_NODE_STATE_RUNNING = 3,
|
||||
};
|
||||
|
||||
const char * pinos_node_state_as_string (PinosNodeState state);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,11 @@ id_map_get_uri (SpaIDMap *map, uint32_t id)
|
|||
IDMap *this = SPA_CONTAINER_OF (map, IDMap, map);
|
||||
if (id == SPA_ID_INVALID)
|
||||
return NULL;
|
||||
return pinos_map_lookup (&this->uris, id);
|
||||
|
||||
if (SPA_LIKELY (pinos_map_check_id (&this->uris, id)))
|
||||
return pinos_map_lookup_unchecked (&this->uris, id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IDMap default_id_map = {
|
||||
|
|
|
|||
|
|
@ -844,8 +844,6 @@ pinos_stream_connect (PinosStream *stream,
|
|||
{
|
||||
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
|
||||
PinosMessageCreateClientNode ccn;
|
||||
SpaDict dict;
|
||||
SpaDictItem items[1];
|
||||
|
||||
impl->direction = direction == PINOS_DIRECTION_INPUT ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT;
|
||||
impl->port_id = 0;
|
||||
|
|
@ -866,7 +864,7 @@ pinos_stream_connect (PinosStream *stream,
|
|||
|
||||
impl->node_proxy = pinos_proxy_new (stream->context,
|
||||
SPA_ID_INVALID,
|
||||
0);
|
||||
stream->context->uri.client_node);
|
||||
|
||||
pinos_proxy_set_dispatch (impl->node_proxy,
|
||||
stream_dispatch_func,
|
||||
|
|
@ -874,11 +872,7 @@ pinos_stream_connect (PinosStream *stream,
|
|||
|
||||
ccn.seq = ++impl->seq;
|
||||
ccn.name = "client-node";
|
||||
dict.n_items = 1;
|
||||
dict.items = items;
|
||||
items[0].key = "pinos.target.node";
|
||||
items[0].value = port_path;
|
||||
ccn.props = &dict;
|
||||
ccn.props = &stream->properties->dict;
|
||||
ccn.new_id = impl->node_proxy->id;
|
||||
|
||||
pinos_proxy_send_message (stream->context->core_proxy,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,16 @@ check_global_owner (PinosCore *core,
|
|||
PinosGlobal *global;
|
||||
|
||||
global = pinos_map_lookup (&core->objects, id);
|
||||
if (global == NULL)
|
||||
return false;
|
||||
|
||||
return (global && global->owner == client);
|
||||
if (global->owner == NULL)
|
||||
return true;
|
||||
|
||||
if (global->owner->ucred.uid == client->ucred.uid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
|
|||
|
||||
error:
|
||||
{
|
||||
pinos_node_update_state (node, PINOS_NODE_STATE_ERROR, error);
|
||||
pinos_log_error ("module %p: can't link node '%s'", impl, error);
|
||||
free (error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -271,6 +272,6 @@ module_destroy (ModuleImpl *impl)
|
|||
bool
|
||||
pinos__module_init (PinosModule * module, const char * args)
|
||||
{
|
||||
module_new (module->core, NULL);
|
||||
module->user_data = module_new (module->core, NULL);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ client_new (PinosProtocolDBus *impl,
|
|||
PinosProtocolDBusClient *this;
|
||||
PinosClient *client;
|
||||
|
||||
client = pinos_client_new (impl->core, NULL);
|
||||
client = pinos_client_new (impl->core, NULL, NULL);
|
||||
|
||||
if ((this = (PinosProtocolDBusClient *) find_object (impl, client))) {
|
||||
pinos_client1_set_sender (this->parent.iface, sender);
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ client_new (PinosProtocolNative *impl,
|
|||
PinosProtocolNativeClient *this;
|
||||
PinosClient *client;
|
||||
socklen_t len;
|
||||
struct ucred ucred, *ucredp;
|
||||
|
||||
this = calloc (1, sizeof (PinosProtocolNativeClient));
|
||||
if (this == NULL)
|
||||
|
|
@ -200,7 +201,15 @@ client_new (PinosProtocolNative *impl,
|
|||
if (this->connection == NULL)
|
||||
goto no_connection;
|
||||
|
||||
client = pinos_client_new (impl->core, NULL);
|
||||
len = sizeof (ucred);
|
||||
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
|
||||
pinos_log_error ("no peercred: %m");
|
||||
ucredp = NULL;
|
||||
} else {
|
||||
ucredp = &ucred;
|
||||
}
|
||||
|
||||
client = pinos_client_new (impl->core, ucredp, NULL);
|
||||
if (client == NULL)
|
||||
goto no_client;
|
||||
|
||||
|
|
@ -210,14 +219,6 @@ client_new (PinosProtocolNative *impl,
|
|||
client_send_func,
|
||||
this);
|
||||
|
||||
len = sizeof (client->ucred);
|
||||
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &client->ucred, &len) < 0) {
|
||||
client->ucred_valid = false;
|
||||
pinos_log_error ("no peercred: %m");
|
||||
} else {
|
||||
client->ucred_valid = true;
|
||||
}
|
||||
|
||||
spa_list_insert (impl->client_list.prev, &this->link);
|
||||
|
||||
pinos_global_bind (impl->core->global,
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ pinos__module_init (PinosModule * module, const char * args)
|
|||
}
|
||||
}
|
||||
free (argv);
|
||||
pinos_free_strv (tmp_argv);
|
||||
}
|
||||
|
||||
pinos_spa_monitor_load (module->core, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor");
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ typedef struct
|
|||
|
||||
SpaProxy proxy;
|
||||
|
||||
PinosListener node_free;
|
||||
PinosListener transport_changed;
|
||||
PinosListener loop_changed;
|
||||
PinosListener global_added;
|
||||
|
|
@ -177,6 +178,9 @@ spa_proxy_node_send_command (SpaNode *node,
|
|||
|
||||
this = SPA_CONTAINER_OF (node, SpaProxy, node);
|
||||
|
||||
if (this->resource == NULL)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
switch (command->type) {
|
||||
case SPA_NODE_COMMAND_INVALID:
|
||||
return SPA_RESULT_INVALID_COMMAND;
|
||||
|
|
@ -200,7 +204,6 @@ spa_proxy_node_send_command (SpaNode *node,
|
|||
uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA;
|
||||
write (this->data_source.fd, &cmd, 1);
|
||||
}
|
||||
|
||||
res = SPA_RESULT_RETURN_ASYNC (cnc.seq);
|
||||
break;
|
||||
}
|
||||
|
|
@ -312,17 +315,22 @@ do_update_port (SpaProxy *this,
|
|||
for (i = 0; i < port->n_formats; i++)
|
||||
free (port->formats[i]);
|
||||
port->n_formats = pu->n_possible_formats;
|
||||
if (port->n_formats)
|
||||
port->formats = realloc (port->formats, port->n_formats * sizeof (SpaFormat *));
|
||||
else {
|
||||
free (port->formats);
|
||||
port->formats = NULL;
|
||||
}
|
||||
for (i = 0; i < port->n_formats; i++) {
|
||||
size = pinos_serialize_format_get_size (pu->possible_formats[i]);
|
||||
port->formats[i] = pinos_serialize_format_copy_into (malloc (size), pu->possible_formats[i]);
|
||||
port->formats[i] = size ? pinos_serialize_format_copy_into (malloc (size), pu->possible_formats[i]) : NULL;
|
||||
}
|
||||
}
|
||||
if (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_FORMAT) {
|
||||
if (port->format)
|
||||
free (port->format);
|
||||
size = pinos_serialize_format_get_size (pu->format);
|
||||
port->format = pinos_serialize_format_copy_into (malloc (size), pu->format);
|
||||
port->format = size ? pinos_serialize_format_copy_into (malloc (size), pu->format) : NULL;
|
||||
}
|
||||
|
||||
if (pu->change_mask & PINOS_MESSAGE_PORT_UPDATE_PROPS) {
|
||||
|
|
@ -332,7 +340,7 @@ do_update_port (SpaProxy *this,
|
|||
if (port->info)
|
||||
free (port->info);
|
||||
size = pinos_serialize_port_info_get_size (pu->info);
|
||||
port->info = pinos_serialize_port_info_copy_into (malloc (size), pu->info);
|
||||
port->info = size ? pinos_serialize_port_info_copy_into (malloc (size), pu->info) : NULL;
|
||||
}
|
||||
|
||||
if (!port->valid) {
|
||||
|
|
@ -482,6 +490,9 @@ spa_proxy_node_port_set_format (SpaNode *node,
|
|||
if (!CHECK_PORT (this, direction, port_id))
|
||||
return SPA_RESULT_INVALID_PORT;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
sf.seq = this->seq++;
|
||||
sf.direction = direction;
|
||||
sf.port_id = port_id;
|
||||
|
|
@ -641,6 +652,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
|||
mb = NULL;
|
||||
}
|
||||
|
||||
port->n_buffers = n_buffers;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
n_mem = 0;
|
||||
for (i = 0; i < n_buffers; i++) {
|
||||
ProxyBuffer *b = &port->buffers[i];
|
||||
|
|
@ -715,8 +731,6 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
|
|||
}
|
||||
}
|
||||
|
||||
port->n_buffers = n_buffers;
|
||||
|
||||
ub.seq = this->seq++;
|
||||
ub.direction = direction;
|
||||
ub.port_id = port_id;
|
||||
|
|
@ -1169,6 +1183,9 @@ on_transport_changed (PinosListener *listener,
|
|||
PinosTransportInfo info;
|
||||
PinosMessageTransportUpdate tu;
|
||||
|
||||
if (this->resource == NULL)
|
||||
return;
|
||||
|
||||
pinos_transport_get_info (node->transport, &info);
|
||||
|
||||
tu.memfd = info.memfd;
|
||||
|
|
@ -1194,6 +1211,7 @@ on_global_added (PinosListener *listener,
|
|||
PinosGlobal *global)
|
||||
{
|
||||
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, global_added);
|
||||
|
||||
if (global->object == impl->this.node)
|
||||
global->owner = impl->this.client;
|
||||
}
|
||||
|
|
@ -1222,7 +1240,25 @@ proxy_clear (SpaProxy *this)
|
|||
static void
|
||||
client_node_resource_destroy (PinosResource *resource)
|
||||
{
|
||||
pinos_client_node_destroy (resource->object);
|
||||
PinosClientNode *this = resource->object;
|
||||
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this);
|
||||
|
||||
impl->proxy.resource = this->resource = NULL;
|
||||
pinos_client_node_destroy (this);
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_free (PinosListener *listener,
|
||||
PinosNode *node)
|
||||
{
|
||||
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, node_free);
|
||||
|
||||
pinos_log_debug ("client-node %p: free", &impl->this);
|
||||
proxy_clear (&impl->proxy);
|
||||
|
||||
if (impl->data_fd != -1)
|
||||
close (impl->data_fd);
|
||||
free (impl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1249,6 +1285,8 @@ pinos_client_node_new (PinosClient *client,
|
|||
return NULL;
|
||||
|
||||
this = &impl->this;
|
||||
this->client = client;
|
||||
|
||||
impl->core = client->core;
|
||||
impl->data_fd = -1;
|
||||
pinos_log_debug ("client-node %p: new", impl);
|
||||
|
|
@ -1277,6 +1315,10 @@ pinos_client_node_new (PinosClient *client,
|
|||
|
||||
impl->proxy.resource = this->resource;
|
||||
|
||||
pinos_signal_add (&this->node->free_signal,
|
||||
&impl->node_free,
|
||||
on_node_free);
|
||||
|
||||
pinos_signal_add (&this->node->transport_changed,
|
||||
&impl->transport_changed,
|
||||
on_transport_changed);
|
||||
|
|
@ -1303,24 +1345,6 @@ error_no_node:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_remove (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosClientNode *this = object;
|
||||
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this);
|
||||
|
||||
pinos_log_debug ("client-node %p: finalize", this);
|
||||
proxy_clear (&impl->proxy);
|
||||
|
||||
if (impl->data_fd != -1)
|
||||
close (impl->data_fd);
|
||||
free (impl);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pinos_client_node_destroy (PinosClientNode * this)
|
||||
{
|
||||
|
|
@ -1330,14 +1354,10 @@ pinos_client_node_destroy (PinosClientNode * this)
|
|||
pinos_signal_emit (&this->destroy_signal, this);
|
||||
|
||||
pinos_signal_remove (&impl->global_added);
|
||||
pinos_signal_remove (&impl->loop_changed);
|
||||
pinos_signal_remove (&impl->transport_changed);
|
||||
|
||||
pinos_node_destroy (this->node);
|
||||
|
||||
pinos_main_loop_defer (this->node->core->main_loop,
|
||||
this,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
(PinosDeferFunc) on_node_remove,
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ no_mem:
|
|||
*/
|
||||
PinosClient *
|
||||
pinos_client_new (PinosCore *core,
|
||||
struct ucred *ucred,
|
||||
PinosProperties *properties)
|
||||
{
|
||||
PinosClient *this;
|
||||
|
|
@ -123,6 +124,8 @@ pinos_client_new (PinosCore *core,
|
|||
|
||||
this = &impl->this;
|
||||
this->core = core;
|
||||
if ((this->ucred_valid = (ucred != NULL)))
|
||||
this->ucred = *ucred;
|
||||
this->properties = properties;
|
||||
|
||||
spa_list_init (&this->resource_list);
|
||||
|
|
@ -142,23 +145,6 @@ pinos_client_new (PinosCore *core,
|
|||
return this;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosClientImpl *impl = SPA_CONTAINER_OF (object, PinosClientImpl, this);
|
||||
PinosClient *client = &impl->this;
|
||||
|
||||
pinos_log_debug ("client %p: sync destroy", impl);
|
||||
|
||||
if (client->properties)
|
||||
pinos_properties_free (client->properties);
|
||||
|
||||
free (impl);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_resource (void *object,
|
||||
void *data)
|
||||
|
|
@ -176,23 +162,26 @@ void
|
|||
pinos_client_destroy (PinosClient * client)
|
||||
{
|
||||
PinosResource *resource, *tmp;
|
||||
PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this);
|
||||
|
||||
pinos_log_debug ("client %p: destroy", client);
|
||||
pinos_signal_emit (&client->destroy_signal, client);
|
||||
|
||||
pinos_map_for_each (&client->objects, destroy_resource, client);
|
||||
|
||||
pinos_global_destroy (client->global);
|
||||
spa_list_remove (&client->link);
|
||||
pinos_global_destroy (client->global);
|
||||
|
||||
spa_list_for_each_safe (resource, tmp, &client->resource_list, link)
|
||||
pinos_resource_destroy (resource);
|
||||
|
||||
pinos_main_loop_defer (client->core->main_loop,
|
||||
client,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
client);
|
||||
pinos_map_for_each (&client->objects, destroy_resource, client);
|
||||
|
||||
pinos_log_debug ("client %p: free", impl);
|
||||
pinos_map_clear (&client->objects);
|
||||
|
||||
if (client->properties)
|
||||
pinos_properties_free (client->properties);
|
||||
|
||||
free (impl);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ struct _PinosClient {
|
|||
};
|
||||
|
||||
PinosClient * pinos_client_new (PinosCore *core,
|
||||
struct ucred *ucred,
|
||||
PinosProperties *properties);
|
||||
void pinos_client_destroy (PinosClient *client);
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,13 @@ no_mem:
|
|||
return SPA_RESULT_NO_MEMORY;
|
||||
}
|
||||
|
||||
static void
|
||||
core_unbind_func (void *data)
|
||||
{
|
||||
PinosResource *resource = data;
|
||||
resource->client->core_resource = NULL;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
core_bind_func (PinosGlobal *global,
|
||||
PinosClient *client,
|
||||
|
|
@ -207,7 +214,7 @@ core_bind_func (PinosGlobal *global,
|
|||
id,
|
||||
global->type,
|
||||
global->object,
|
||||
NULL);
|
||||
core_unbind_func);
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
|
||||
|
|
@ -310,10 +317,14 @@ pinos_core_destroy (PinosCore *core)
|
|||
{
|
||||
PinosCoreImpl *impl = SPA_CONTAINER_OF (core, PinosCoreImpl, this);
|
||||
|
||||
pinos_log_debug ("core %p: destroy", core);
|
||||
pinos_signal_emit (&core->destroy_signal, core);
|
||||
|
||||
pinos_data_loop_destroy (core->data_loop);
|
||||
|
||||
pinos_map_clear (&core->objects);
|
||||
|
||||
pinos_log_debug ("core %p: free", core);
|
||||
free (impl);
|
||||
}
|
||||
|
||||
|
|
@ -350,10 +361,11 @@ pinos_core_add_global (PinosCore *core,
|
|||
spa_list_insert (core->global_list.prev, &this->link);
|
||||
pinos_signal_emit (&core->global_added, core, this);
|
||||
|
||||
pinos_log_debug ("global %p: new %u", this, this->id);
|
||||
|
||||
ng.id = this->id;
|
||||
ng.type = spa_id_map_get_uri (core->uri.map, this->type);
|
||||
|
||||
pinos_log_debug ("global %p: new %u %s", this, ng.id, ng.type);
|
||||
|
||||
spa_list_for_each (registry, &core->registry_resource_list, link) {
|
||||
pinos_resource_send_message (registry,
|
||||
PINOS_MESSAGE_NOTIFY_GLOBAL,
|
||||
|
|
@ -384,18 +396,6 @@ pinos_global_bind (PinosGlobal *global,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosGlobal *global = object;
|
||||
|
||||
pinos_log_debug ("global %p: sync destroy", global);
|
||||
free (global);
|
||||
}
|
||||
|
||||
void
|
||||
pinos_global_destroy (PinosGlobal *global)
|
||||
{
|
||||
|
|
@ -406,11 +406,6 @@ pinos_global_destroy (PinosGlobal *global)
|
|||
pinos_log_debug ("global %p: destroy %u", global, global->id);
|
||||
pinos_signal_emit (&global->destroy_signal, global);
|
||||
|
||||
pinos_map_remove (&core->objects, global->id);
|
||||
|
||||
spa_list_remove (&global->link);
|
||||
pinos_signal_emit (&core->global_removed, core, global);
|
||||
|
||||
ng.id = global->id;
|
||||
spa_list_for_each (registry, &core->registry_resource_list, link) {
|
||||
pinos_resource_send_message (registry,
|
||||
|
|
@ -419,11 +414,13 @@ pinos_global_destroy (PinosGlobal *global)
|
|||
true);
|
||||
}
|
||||
|
||||
pinos_main_loop_defer (core->main_loop,
|
||||
global,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
global);
|
||||
pinos_map_remove (&core->objects, global->id);
|
||||
|
||||
spa_list_remove (&global->link);
|
||||
pinos_signal_emit (&core->global_removed, core, global);
|
||||
|
||||
pinos_log_debug ("global %p: free", global);
|
||||
free (global);
|
||||
}
|
||||
|
||||
PinosPort *
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ typedef struct
|
|||
{
|
||||
PinosLink this;
|
||||
|
||||
int refcount;
|
||||
|
||||
uint32_t seq;
|
||||
|
||||
SpaFormat **format_filter;
|
||||
|
|
@ -648,25 +650,12 @@ on_output_async_complete_notify (PinosListener *listener,
|
|||
pinos_main_loop_defer_complete (this->core->main_loop, impl, seq, res);
|
||||
}
|
||||
|
||||
static void
|
||||
on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, uint32_t id)
|
||||
{
|
||||
pinos_signal_emit (&this->core->port_unlinked, this, port);
|
||||
|
||||
if (this->input == NULL || this->output == NULL) {
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL);
|
||||
pinos_link_destroy (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_port_destroy (PinosLink *this,
|
||||
PinosPort *port)
|
||||
{
|
||||
PinosLinkImpl *impl = (PinosLinkImpl *) this;
|
||||
PinosPort *other;
|
||||
SpaResult res = SPA_RESULT_OK;
|
||||
|
||||
if (port == this->input) {
|
||||
pinos_log_debug ("link %p: input port destroyed %p", this, port);
|
||||
|
|
@ -691,11 +680,10 @@ on_port_destroy (PinosLink *this,
|
|||
pinos_port_clear_buffers (other);
|
||||
}
|
||||
|
||||
pinos_main_loop_defer (this->core->main_loop,
|
||||
port,
|
||||
res,
|
||||
(PinosDeferFunc) on_port_unlinked,
|
||||
this);
|
||||
pinos_signal_emit (&this->core->port_unlinked, this, port);
|
||||
|
||||
pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL);
|
||||
pinos_link_destroy (this);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -749,11 +737,31 @@ link_dispatch_func (void *object,
|
|||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
pinos_link_free (PinosLink *link)
|
||||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (link, PinosLinkImpl, this);
|
||||
|
||||
pinos_log_debug ("link %p: free", link);
|
||||
pinos_signal_emit (&link->free_signal, link);
|
||||
|
||||
if (impl->allocated)
|
||||
pinos_memblock_free (&impl->buffer_mem);
|
||||
|
||||
free (impl);
|
||||
}
|
||||
|
||||
static void
|
||||
link_unbind_func (void *data)
|
||||
{
|
||||
PinosResource *resource = data;
|
||||
PinosLink *this = resource->object;
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
|
||||
spa_list_remove (&resource->link);
|
||||
|
||||
if (--impl->refcount == 0)
|
||||
pinos_link_free (this);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -763,6 +771,7 @@ link_bind_func (PinosGlobal *global,
|
|||
uint32_t id)
|
||||
{
|
||||
PinosLink *this = global->object;
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
PinosResource *resource;
|
||||
PinosMessageLinkInfo m;
|
||||
PinosLinkInfo info;
|
||||
|
|
@ -775,6 +784,8 @@ link_bind_func (PinosGlobal *global,
|
|||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
|
||||
impl->refcount++;
|
||||
|
||||
pinos_resource_set_dispatch (resource,
|
||||
link_dispatch_func,
|
||||
global);
|
||||
|
|
@ -790,6 +801,7 @@ link_bind_func (PinosGlobal *global,
|
|||
info.output_port_id = this->output ? this->output->port_id : -1;
|
||||
info.input_node_id = this->input ? this->input->node->global->id : -1;
|
||||
info.input_port_id = this->input ? this->input->port_id : -1;
|
||||
|
||||
return pinos_resource_send_message (resource,
|
||||
PINOS_MESSAGE_LINK_INFO,
|
||||
&m,
|
||||
|
|
@ -821,12 +833,14 @@ pinos_link_new (PinosCore *core,
|
|||
this->core = core;
|
||||
this->properties = properties;
|
||||
this->state = PINOS_LINK_STATE_INIT;
|
||||
impl->refcount = 1;
|
||||
|
||||
this->input = input;
|
||||
this->output = output;
|
||||
|
||||
spa_list_init (&this->resource_list);
|
||||
pinos_signal_init (&this->destroy_signal);
|
||||
pinos_signal_init (&this->free_signal);
|
||||
|
||||
impl->format_filter = format_filter;
|
||||
|
||||
|
|
@ -884,6 +898,7 @@ do_link_remove_done (SpaLoop *loop,
|
|||
void *user_data)
|
||||
{
|
||||
PinosLink *this = user_data;
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
|
||||
if (this->input) {
|
||||
spa_list_remove (&this->input_link);
|
||||
|
|
@ -907,11 +922,8 @@ do_link_remove_done (SpaLoop *loop,
|
|||
clear_port_buffers (this, this->output);
|
||||
this->output = NULL;
|
||||
}
|
||||
|
||||
pinos_main_loop_defer_complete (this->core->main_loop,
|
||||
this,
|
||||
seq,
|
||||
SPA_RESULT_OK);
|
||||
if (--impl->refcount == 0)
|
||||
pinos_link_free (this);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -945,22 +957,6 @@ do_link_remove (SpaLoop *loop,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (object, PinosLinkImpl, this);
|
||||
|
||||
pinos_log_debug ("link %p: sync destroy", impl);
|
||||
|
||||
if (impl->allocated)
|
||||
pinos_memblock_free (&impl->buffer_mem);
|
||||
|
||||
free (impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_link_destroy:
|
||||
* @link: a #PinosLink
|
||||
|
|
@ -970,7 +966,6 @@ sync_destroy (void *object,
|
|||
void
|
||||
pinos_link_destroy (PinosLink * this)
|
||||
{
|
||||
SpaResult res = SPA_RESULT_OK;
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
PinosResource *resource, *tmp;
|
||||
|
||||
|
|
@ -987,31 +982,26 @@ pinos_link_destroy (PinosLink * this)
|
|||
pinos_signal_remove (&impl->input_port_destroy);
|
||||
pinos_signal_remove (&impl->input_async_complete);
|
||||
|
||||
res = pinos_loop_invoke (this->input->node->data_loop->loop,
|
||||
impl->refcount++;
|
||||
pinos_loop_invoke (this->input->node->data_loop->loop,
|
||||
do_link_remove,
|
||||
impl->seq++,
|
||||
0,
|
||||
NULL,
|
||||
this);
|
||||
|
||||
pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL);
|
||||
}
|
||||
if (this->output) {
|
||||
pinos_signal_remove (&impl->output_port_destroy);
|
||||
pinos_signal_remove (&impl->output_async_complete);
|
||||
|
||||
res = pinos_loop_invoke (this->output->node->data_loop->loop,
|
||||
impl->refcount++;
|
||||
pinos_loop_invoke (this->output->node->data_loop->loop,
|
||||
do_link_remove,
|
||||
impl->seq++,
|
||||
0,
|
||||
NULL,
|
||||
this);
|
||||
pinos_main_loop_defer (this->core->main_loop, this, res, NULL, NULL);
|
||||
}
|
||||
|
||||
pinos_main_loop_defer (this->core->main_loop,
|
||||
this,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
this);
|
||||
if (--impl->refcount == 0)
|
||||
pinos_link_free (this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ struct _PinosLink {
|
|||
|
||||
PINOS_SIGNAL (destroy_signal, (PinosListener *,
|
||||
PinosLink *));
|
||||
PINOS_SIGNAL (free_signal, (PinosListener *,
|
||||
PinosLink *));
|
||||
|
||||
SpaList resource_list;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ struct _PinosModule {
|
|||
char *filename;
|
||||
char *args;
|
||||
|
||||
void *user_data;
|
||||
|
||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||
PinosModule *module));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -461,10 +461,9 @@ init_complete (PinosNode *this)
|
|||
pinos_log_debug ("node %p: init completed", this);
|
||||
impl->async_init = false;
|
||||
|
||||
spa_list_insert (this->core->node_list.prev, &this->link);
|
||||
|
||||
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
|
||||
|
||||
spa_list_insert (this->core->node_list.prev, &this->link);
|
||||
this->global = pinos_core_add_global (this->core,
|
||||
NULL,
|
||||
this->core->uri.node,
|
||||
|
|
@ -512,6 +511,7 @@ pinos_node_new (PinosCore *core,
|
|||
pinos_log_warn ("node %p: error setting callback", this);
|
||||
|
||||
pinos_signal_init (&this->destroy_signal);
|
||||
pinos_signal_init (&this->free_signal);
|
||||
pinos_signal_init (&this->async_complete);
|
||||
pinos_signal_init (&this->transport_changed);
|
||||
pinos_signal_init (&this->loop_changed);
|
||||
|
|
@ -564,6 +564,7 @@ do_node_remove_done (SpaLoop *loop,
|
|||
void *user_data)
|
||||
{
|
||||
PinosNode *this = user_data;
|
||||
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
|
||||
PinosPort *port, *tmp;
|
||||
|
||||
pinos_log_debug ("node %p: remove done, destroy ports", this);
|
||||
|
|
@ -573,10 +574,21 @@ do_node_remove_done (SpaLoop *loop,
|
|||
spa_list_for_each_safe (port, tmp, &this->output_ports, link)
|
||||
pinos_port_destroy (port);
|
||||
|
||||
pinos_main_loop_defer_complete (this->core->main_loop,
|
||||
this,
|
||||
seq,
|
||||
SPA_RESULT_OK);
|
||||
pinos_log_debug ("node %p: free", this);
|
||||
pinos_signal_emit (&this->free_signal, this);
|
||||
|
||||
if (this->transport)
|
||||
pinos_transport_destroy (this->transport);
|
||||
if (this->input_port_map)
|
||||
free (this->input_port_map);
|
||||
if (this->output_port_map)
|
||||
free (this->output_port_map);
|
||||
|
||||
free (this->name);
|
||||
free (this->error);
|
||||
if (this->properties)
|
||||
pinos_properties_free (this->properties);
|
||||
free (impl);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
}
|
||||
|
|
@ -620,24 +632,6 @@ do_node_remove (SpaLoop *loop,
|
|||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosNode *this = object;
|
||||
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
|
||||
|
||||
pinos_log_debug ("node %p: sync destroy", this);
|
||||
|
||||
free (this->name);
|
||||
free (this->error);
|
||||
if (this->properties)
|
||||
pinos_properties_free (this->properties);
|
||||
free (impl);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_destroy:
|
||||
* @node: a #PinosNode
|
||||
|
|
@ -648,7 +642,6 @@ sync_destroy (void *object,
|
|||
void
|
||||
pinos_node_destroy (PinosNode * this)
|
||||
{
|
||||
SpaResult res;
|
||||
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
|
||||
PinosResource *resource, *tmp;
|
||||
|
||||
|
|
@ -661,24 +654,12 @@ pinos_node_destroy (PinosNode * this)
|
|||
spa_list_for_each_safe (resource, tmp, &this->resource_list, link)
|
||||
pinos_resource_destroy (resource);
|
||||
|
||||
res = pinos_loop_invoke (this->data_loop->loop,
|
||||
pinos_loop_invoke (this->data_loop->loop,
|
||||
do_node_remove,
|
||||
impl->seq++,
|
||||
0,
|
||||
NULL,
|
||||
this);
|
||||
|
||||
pinos_main_loop_defer (this->core->main_loop,
|
||||
this,
|
||||
res,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
pinos_main_loop_defer (this->core->main_loop,
|
||||
this,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -771,9 +752,6 @@ pinos_node_set_state (PinosNode *node,
|
|||
res = suspend_node (node);
|
||||
break;
|
||||
|
||||
case PINOS_NODE_STATE_INITIALIZING:
|
||||
break;
|
||||
|
||||
case PINOS_NODE_STATE_IDLE:
|
||||
res = pause_node (node);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ struct _PinosNode {
|
|||
|
||||
PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
|
||||
PinosNode *object));
|
||||
PINOS_SIGNAL (free_signal, (PinosListener *listener,
|
||||
PinosNode *object));
|
||||
|
||||
PINOS_SIGNAL (async_complete, (PinosListener *listener,
|
||||
PinosNode *node,
|
||||
|
|
|
|||
|
|
@ -56,17 +56,6 @@ pinos_port_new (PinosNode *node,
|
|||
return this;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosPort *port = object;
|
||||
|
||||
free (port);
|
||||
}
|
||||
|
||||
void
|
||||
pinos_port_destroy (PinosPort *port)
|
||||
{
|
||||
|
|
@ -83,11 +72,7 @@ pinos_port_destroy (PinosPort *port)
|
|||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
|
||||
pinos_main_loop_defer (port->node->core->main_loop,
|
||||
port,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
port);
|
||||
free (port);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
|
|||
|
|
@ -59,28 +59,12 @@ pinos_resource_new (PinosClient *client,
|
|||
return this;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_destroy (void *object,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosResource *resource = object;
|
||||
pinos_log_debug ("resource %p: sync destroy", resource);
|
||||
free (resource);
|
||||
}
|
||||
|
||||
SpaResult
|
||||
void
|
||||
pinos_resource_destroy (PinosResource *resource)
|
||||
{
|
||||
pinos_log_debug ("resource %p: destroy", resource);
|
||||
pinos_signal_emit (&resource->destroy_signal, resource);
|
||||
|
||||
pinos_map_remove (&resource->client->objects, resource->id);
|
||||
|
||||
if (resource->destroy)
|
||||
resource->destroy (resource);
|
||||
|
||||
if (resource->client->core_resource) {
|
||||
PinosMessageRemoveId m;
|
||||
m.id = resource->id;
|
||||
|
|
@ -90,13 +74,13 @@ pinos_resource_destroy (PinosResource *resource)
|
|||
true);
|
||||
}
|
||||
|
||||
pinos_main_loop_defer (resource->core->main_loop,
|
||||
resource,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
sync_destroy,
|
||||
resource);
|
||||
pinos_map_remove (&resource->client->objects, resource->id);
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
if (resource->destroy)
|
||||
resource->destroy (resource);
|
||||
|
||||
pinos_log_debug ("resource %p: free", resource);
|
||||
free (resource);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ PinosResource * pinos_resource_new (PinosClient *client,
|
|||
uint32_t type,
|
||||
void *object,
|
||||
PinosDestroy destroy);
|
||||
SpaResult pinos_resource_destroy (PinosResource *resource);
|
||||
void pinos_resource_destroy (PinosResource *resource);
|
||||
|
||||
void pinos_resource_set_dispatch (PinosResource *resource,
|
||||
PinosDispatchFunc func,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue