improve error reporting

Move signals from core to the objects themselves
Use per object info to track object signals
Use periods in alsasink and source
This commit is contained in:
Wim Taymans 2017-01-17 10:27:58 +01:00
parent fb69758251
commit cae971e106
23 changed files with 573 additions and 384 deletions

View file

@ -25,6 +25,7 @@
#include "pinos/server/core.h"
#include "pinos/server/module.h"
#include "pinos/server/client-node.h"
typedef struct {
PinosCore *core;
@ -32,15 +33,142 @@ typedef struct {
PinosListener global_added;
PinosListener global_removed;
PinosListener port_added;
PinosListener port_removed;
PinosListener port_unlinked;
PinosListener link_state_changed;
SpaList node_list;
SpaList client_list;
} ModuleImpl;
static void
try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
typedef struct {
ModuleImpl *impl;
PinosClient *client;
SpaList link;
PinosListener resource_added;
PinosListener resource_removed;
} ClientInfo;
typedef struct {
ModuleImpl *impl;
ClientInfo *info;
PinosNode *node;
PinosResource *resource;
SpaList link;
PinosListener state_changed;
PinosListener port_added;
PinosListener port_removed;
PinosListener port_unlinked;
PinosListener link_state_changed;
} NodeInfo;
static NodeInfo *
find_node_info (ModuleImpl *impl, PinosNode *node)
{
NodeInfo *info;
spa_list_for_each (info, &impl->node_list, link) {
if (info->node == node)
return info;
}
return NULL;
}
static ClientInfo *
find_client_info (ModuleImpl *impl, PinosClient *client)
{
ClientInfo *info;
spa_list_for_each (info, &impl->client_list, link) {
if (info->client == client)
return info;
}
return NULL;
}
static void
node_info_free (NodeInfo *info)
{
spa_list_remove (&info->link);
pinos_signal_remove (&info->state_changed);
pinos_signal_remove (&info->port_added);
pinos_signal_remove (&info->port_removed);
pinos_signal_remove (&info->port_unlinked);
pinos_signal_remove (&info->link_state_changed);
free (info);
}
static void
client_info_free (ClientInfo *cinfo)
{
spa_list_remove (&cinfo->link);
pinos_signal_remove (&cinfo->resource_added);
pinos_signal_remove (&cinfo->resource_removed);
free (cinfo);
}
static void try_link_port (PinosNode *node, PinosPort *port, NodeInfo *info);
static void
on_link_port_unlinked (PinosListener *listener,
PinosLink *link,
PinosPort *port)
{
NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, port_unlinked);
ModuleImpl *impl = info->impl;
pinos_log_debug ("module %p: link %p: port %p unlinked", impl, link, port);
if (port->direction == PINOS_DIRECTION_OUTPUT && link->input)
try_link_port (link->input->node, link->input, info);
}
static void
on_link_state_changed (PinosListener *listener,
PinosLink *link,
PinosLinkState old,
PinosLinkState state)
{
NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, link_state_changed);
ModuleImpl *impl = info->impl;
switch (state) {
case PINOS_LINK_STATE_ERROR:
{
PinosResource *resource;
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
spa_list_for_each (resource, &link->resource_list, link) {
pinos_client_send_error (resource->client,
resource,
SPA_RESULT_ERROR,
link->error);
}
if (info->info->client) {
pinos_client_send_error (info->info->client,
info->resource,
SPA_RESULT_ERROR,
link->error);
}
break;
}
case PINOS_LINK_STATE_UNLINKED:
pinos_log_debug ("module %p: link %p: unlinked", impl, link);
break;
case PINOS_LINK_STATE_INIT:
case PINOS_LINK_STATE_NEGOTIATING:
case PINOS_LINK_STATE_ALLOCATING:
case PINOS_LINK_STATE_PAUSED:
case PINOS_LINK_STATE_RUNNING:
break;
}
}
static void
try_link_port (PinosNode *node,
PinosPort *port,
NodeInfo *info)
{
ModuleImpl *impl = info->impl;
PinosProperties *props;
const char *path;
char *error = NULL;
@ -76,6 +204,9 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
if (link == NULL)
goto error;
pinos_signal_add (&link->port_unlinked, &info->port_unlinked, on_link_port_unlinked);
pinos_signal_add (&link->state_changed, &info->link_state_changed, on_link_state_changed);
pinos_link_activate (link);
}
return;
@ -83,80 +214,25 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
error:
{
pinos_log_error ("module %p: can't link node '%s'", impl, error);
if (info->info->client) {
pinos_client_send_error (info->info->client,
info->resource,
SPA_RESULT_ERROR,
error);
}
free (error);
return;
}
}
static void
on_link_port_unlinked (PinosListener *listener,
PinosLink *link,
PinosPort *port)
{
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, port_unlinked);
pinos_log_debug ("module %p: link %p: port %p unlinked", impl, link, port);
if (port->direction == PINOS_DIRECTION_OUTPUT && link->input)
try_link_port (link->input->node, link->input, impl);
}
static void
on_link_state_changed (PinosListener *listener,
PinosLink *link)
{
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, link_state_changed);
PinosLinkState state;
state = link->state;
switch (state) {
case PINOS_LINK_STATE_ERROR:
{
PinosResource *resource;
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
spa_list_for_each (resource, &link->resource_list, link) {
pinos_resource_send_error (resource,
SPA_RESULT_ERROR,
link->error);
}
#if 0
if (link->input && link->input->node)
pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
if (link->output && link->output->node)
pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
#endif
break;
}
case PINOS_LINK_STATE_UNLINKED:
pinos_log_debug ("module %p: link %p: unlinked", impl, link);
#if 0
if (link->input && link->input->node)
pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
if (link->output && link->output->node)
pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
#endif
break;
case PINOS_LINK_STATE_INIT:
case PINOS_LINK_STATE_NEGOTIATING:
case PINOS_LINK_STATE_ALLOCATING:
case PINOS_LINK_STATE_PAUSED:
case PINOS_LINK_STATE_RUNNING:
break;
}
}
static void
on_port_added (PinosListener *listener,
PinosNode *node,
PinosPort *port)
{
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, port_added);
NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, port_added);
try_link_port (node, port, impl);
try_link_port (node, port, info);
}
static void
@ -168,30 +244,87 @@ on_port_removed (PinosListener *listener,
static void
on_node_created (PinosNode *node,
ModuleImpl *impl)
NodeInfo *info)
{
PinosPort *port;
spa_list_for_each (port, &node->input_ports, link)
on_port_added (&impl->port_added, node, port);
on_port_added (&info->port_added, node, port);
spa_list_for_each (port, &node->output_ports, link)
on_port_added (&impl->port_added, node, port);
on_port_added (&info->port_added, node, port);
}
static void
on_node_added (ModuleImpl *impl, PinosNode *node)
on_state_changed (PinosListener *listener,
PinosNode *node,
PinosNodeState old,
PinosNodeState state)
{
NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, state_changed);
if (old == PINOS_NODE_STATE_CREATING && state == PINOS_NODE_STATE_SUSPENDED)
on_node_created (node, info);
}
static void
on_node_added (ModuleImpl *impl,
PinosNode *node,
PinosResource *resource,
ClientInfo *cinfo)
{
NodeInfo *info;
info = calloc (1, sizeof (NodeInfo));
info->impl = impl;
info->node = node;
info->resource = resource;
info->info = cinfo;
spa_list_insert (impl->node_list.prev, &info->link);
spa_list_init (&info->port_unlinked.link);
spa_list_init (&info->link_state_changed.link);
pinos_signal_add (&node->port_added, &info->port_added, on_port_added);
pinos_signal_add (&node->port_removed, &info->port_removed, on_port_removed);
pinos_signal_add (&node->state_changed, &info->state_changed, on_state_changed);
pinos_log_debug ("module %p: node %p added", impl, node);
if (node->state > PINOS_NODE_STATE_CREATING)
on_node_created (node, impl);
on_node_created (node, info);
}
static void
on_node_removed (ModuleImpl *impl, PinosNode *node)
on_resource_added (PinosListener *listener,
PinosClient *client,
PinosResource *resource)
{
pinos_log_debug ("module %p: node %p removed", impl, node);
ClientInfo *cinfo = SPA_CONTAINER_OF (listener, ClientInfo, resource_added);
ModuleImpl *impl = cinfo->impl;
if (resource->type == impl->core->uri.client_node) {
PinosClientNode *cnode = resource->object;
on_node_added (impl, cnode->node, resource, cinfo);
}
}
static void
on_resource_removed (PinosListener *listener,
PinosClient *client,
PinosResource *resource)
{
ClientInfo *cinfo = SPA_CONTAINER_OF (listener, ClientInfo, resource_removed);
ModuleImpl *impl = cinfo->impl;
if (resource->type == impl->core->uri.client_node) {
PinosClientNode *cnode = resource->object;
NodeInfo *ninfo;
if ((ninfo = find_node_info (impl, cnode->node)))
node_info_free (ninfo);
pinos_log_debug ("module %p: node %p removed", impl, cnode->node);
}
}
static void
@ -201,9 +334,19 @@ on_global_added (PinosListener *listener,
{
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_added);
if (global->type == impl->core->uri.node) {
PinosNode *node = global->object;
on_node_added (impl, node);
if (global->type == impl->core->uri.client) {
PinosClient *client = global->object;
ClientInfo *cinfo;
cinfo = calloc (1, sizeof (ClientInfo));
cinfo->impl = impl;
cinfo->client = global->object;
spa_list_insert (impl->client_list.prev, &cinfo->link);
pinos_signal_add (&client->resource_added, &cinfo->resource_added, on_resource_added);
pinos_signal_add (&client->resource_removed, &cinfo->resource_removed, on_resource_removed);
pinos_log_debug ("module %p: client %p added", impl, cinfo->client);
}
}
@ -214,9 +357,14 @@ on_global_removed (PinosListener *listener,
{
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_removed);
if (global->type == impl->core->uri.node) {
PinosNode *node = global->object;
on_node_removed (impl, node);
if (global->type == impl->core->uri.client) {
PinosClient *client = global->object;
ClientInfo *cinfo;
if ((cinfo = find_client_info (impl, client)))
client_info_free (cinfo);
pinos_log_debug ("module %p: client %p removed", impl, client);
}
}
@ -241,12 +389,11 @@ module_new (PinosCore *core,
impl->core = core;
impl->properties = properties;
spa_list_init (&impl->node_list);
spa_list_init (&impl->client_list);
pinos_signal_add (&core->global_added, &impl->global_added, on_global_added);
pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
pinos_signal_add (&core->port_added, &impl->port_added, on_port_added);
pinos_signal_add (&core->port_removed, &impl->port_removed, on_port_removed);
pinos_signal_add (&core->port_unlinked, &impl->port_unlinked, on_link_port_unlinked);
pinos_signal_add (&core->link_state_changed, &impl->link_state_changed, on_link_state_changed);
return impl;
}