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

@ -335,8 +335,8 @@ static void *
connection_ensure_size (PinosConnection *conn, ConnectionBuffer *buf, size_t size) connection_ensure_size (PinosConnection *conn, ConnectionBuffer *buf, size_t size)
{ {
if (buf->buffer_size + size > buf->buffer_maxsize) { if (buf->buffer_size + size > buf->buffer_maxsize) {
buf->buffer_maxsize = buf->buffer_size + MAX_BUFFER_SIZE * ((size + MAX_BUFFER_SIZE-1) / MAX_BUFFER_SIZE); buf->buffer_maxsize = SPA_ROUND_UP_N (buf->buffer_size + size, MAX_BUFFER_SIZE);
pinos_log_warn ("connection %p: resize buffer to %zd", conn, buf->buffer_maxsize); pinos_log_warn ("connection %p: resize buffer to %zd %zd %zd", conn, buf->buffer_size, size, buf->buffer_maxsize);
buf->buffer_data = realloc (buf->buffer_data, buf->buffer_maxsize); buf->buffer_data = realloc (buf->buffer_data, buf->buffer_maxsize);
} }
return (uint8_t *) buf->buffer_data + buf->buffer_size; return (uint8_t *) buf->buffer_data + buf->buffer_size;
@ -404,6 +404,7 @@ connection_add_error (PinosConnection *conn,
memcpy (p, m, sizeof (PinosMessageError)); memcpy (p, m, sizeof (PinosMessageError));
d = p; d = p;
p = SPA_MEMBER (d, sizeof (PinosMessageError), void);
if (m->error) { if (m->error) {
strcpy (p, m->error); strcpy (p, m->error);
d->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); d->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d));
@ -1284,6 +1285,7 @@ pinos_connection_parse_message (PinosConnection *conn,
} }
case PINOS_MESSAGE_INVALID: case PINOS_MESSAGE_INVALID:
pinos_log_error ("invalid message %d received", conn->in.type);
return false; return false;
} }
return true; return true;

View file

@ -73,9 +73,6 @@ context_set_state (PinosContext *context,
...) ...)
{ {
if (context->state != state) { if (context->state != state) {
pinos_log_debug ("context %p: update state from %s -> %s", context,
pinos_context_state_as_string (context->state),
pinos_context_state_as_string (state));
if (context->error) if (context->error)
free (context->error); free (context->error);
@ -89,6 +86,10 @@ context_set_state (PinosContext *context,
} else { } else {
context->error = NULL; context->error = NULL;
} }
pinos_log_debug ("context %p: update state from %s -> %s (%s)", context,
pinos_context_state_as_string (context->state),
pinos_context_state_as_string (state),
context->error);
context->state = state; context->state = state;
pinos_signal_emit (&context->state_changed, context); pinos_signal_emit (&context->state_changed, context);
@ -563,7 +564,7 @@ pinos_context_destroy (PinosContext *context)
* Returns: %TRUE on success. * Returns: %TRUE on success.
*/ */
bool bool
pinos_context_connect (PinosContext *context) pinos_context_connect (PinosContext *context)
{ {
PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this); PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this);
struct sockaddr_un addr; struct sockaddr_un addr;

View file

@ -865,6 +865,8 @@ pinos_stream_connect (PinosStream *stream,
impl->node_proxy = pinos_proxy_new (stream->context, impl->node_proxy = pinos_proxy_new (stream->context,
SPA_ID_INVALID, SPA_ID_INVALID,
stream->context->uri.client_node); stream->context->uri.client_node);
if (impl->node_proxy == NULL)
return false;
pinos_proxy_set_dispatch (impl->node_proxy, pinos_proxy_set_dispatch (impl->node_proxy,
stream_dispatch_func, stream_dispatch_func,

View file

@ -571,6 +571,9 @@ gst_pinos_src_stream_start (GstPinosSrc *pinossrc)
if (state == PINOS_STREAM_STATE_ERROR) if (state == PINOS_STREAM_STATE_ERROR)
goto start_error; goto start_error;
if (pinossrc->ctx->state == PINOS_CONTEXT_STATE_ERROR)
goto start_error;
pinos_thread_main_loop_wait (pinossrc->main_loop); pinos_thread_main_loop_wait (pinossrc->main_loop);
} }
@ -604,9 +607,13 @@ wait_negotiated (GstPinosSrc *this)
GST_DEBUG_OBJECT (this, "waiting for started signal, state now %s", GST_DEBUG_OBJECT (this, "waiting for started signal, state now %s",
pinos_stream_state_as_string (state)); pinos_stream_state_as_string (state));
if (state == PINOS_STREAM_STATE_ERROR) if (state == PINOS_STREAM_STATE_ERROR)
break; break;
if (this->ctx->state == PINOS_CONTEXT_STATE_ERROR)
break;
if (this->started) if (this->started)
break; break;
@ -698,6 +705,9 @@ gst_pinos_src_negotiate (GstBaseSrc * basesrc)
if (state == PINOS_STREAM_STATE_ERROR) if (state == PINOS_STREAM_STATE_ERROR)
goto connect_error; goto connect_error;
if (pinossrc->ctx->state == PINOS_CONTEXT_STATE_ERROR)
goto connect_error;
pinos_thread_main_loop_wait (pinossrc->main_loop); pinos_thread_main_loop_wait (pinossrc->main_loop);
} }
pinos_thread_main_loop_unlock (pinossrc->main_loop); pinos_thread_main_loop_unlock (pinossrc->main_loop);

View file

@ -25,6 +25,7 @@
#include "pinos/server/core.h" #include "pinos/server/core.h"
#include "pinos/server/module.h" #include "pinos/server/module.h"
#include "pinos/server/client-node.h"
typedef struct { typedef struct {
PinosCore *core; PinosCore *core;
@ -32,15 +33,142 @@ typedef struct {
PinosListener global_added; PinosListener global_added;
PinosListener global_removed; PinosListener global_removed;
PinosListener port_added;
PinosListener port_removed; SpaList node_list;
PinosListener port_unlinked; SpaList client_list;
PinosListener link_state_changed;
} ModuleImpl; } ModuleImpl;
static void typedef struct {
try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl) 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; PinosProperties *props;
const char *path; const char *path;
char *error = NULL; char *error = NULL;
@ -76,6 +204,9 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
if (link == NULL) if (link == NULL)
goto error; 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); pinos_link_activate (link);
} }
return; return;
@ -83,80 +214,25 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
error: error:
{ {
pinos_log_error ("module %p: can't link node '%s'", 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); free (error);
return; 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 static void
on_port_added (PinosListener *listener, on_port_added (PinosListener *listener,
PinosNode *node, PinosNode *node,
PinosPort *port) 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 static void
@ -168,30 +244,87 @@ on_port_removed (PinosListener *listener,
static void static void
on_node_created (PinosNode *node, on_node_created (PinosNode *node,
ModuleImpl *impl) NodeInfo *info)
{ {
PinosPort *port; PinosPort *port;
spa_list_for_each (port, &node->input_ports, link) 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) 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 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); pinos_log_debug ("module %p: node %p added", impl, node);
if (node->state > PINOS_NODE_STATE_CREATING) if (node->state > PINOS_NODE_STATE_CREATING)
on_node_created (node, impl); on_node_created (node, info);
} }
static void 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 static void
@ -201,9 +334,19 @@ on_global_added (PinosListener *listener,
{ {
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_added); ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_added);
if (global->type == impl->core->uri.node) { if (global->type == impl->core->uri.client) {
PinosNode *node = global->object; PinosClient *client = global->object;
on_node_added (impl, node); 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); ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_removed);
if (global->type == impl->core->uri.node) { if (global->type == impl->core->uri.client) {
PinosNode *node = global->object; PinosClient *client = global->object;
on_node_removed (impl, node); 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->core = core;
impl->properties = properties; 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_added, &impl->global_added, on_global_added);
pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed); 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; return impl;
} }

View file

@ -64,7 +64,6 @@ typedef struct {
PinosListener global_added; PinosListener global_added;
PinosListener global_removed; PinosListener global_removed;
PinosListener node_state_changed;
} PinosProtocolDBus; } PinosProtocolDBus;
typedef struct { typedef struct {
@ -371,16 +370,13 @@ on_node_state_changed (PinosListener *listener,
PinosNodeState old, PinosNodeState old,
PinosNodeState state) PinosNodeState state)
{ {
PinosProtocolDBus *impl = SPA_CONTAINER_OF (listener, PinosProtocolDBus, node_state_changed); PinosProtocolDBusNode *object = SPA_CONTAINER_OF (listener, PinosProtocolDBusNode, state_changed);
PinosProtocolDBusObject *object;
pinos_log_debug ("protocol-dbus %p: node %p state change %s -> %s", impl, node, pinos_log_debug ("protocol-dbus %p: node %p state change %s -> %s", object->parent.impl, node,
pinos_node_state_as_string (old), pinos_node_state_as_string (old),
pinos_node_state_as_string (state)); pinos_node_state_as_string (state));
if ((object = find_object (impl, node))) { pinos_node1_set_state (object->parent.iface, node->state);
pinos_node1_set_state (object->iface, node->state);
}
} }
static bool static bool
@ -550,6 +546,7 @@ on_global_added (PinosListener *listener,
PinosNode *node = global->object; PinosNode *node = global->object;
PinosProperties *props = node->properties; PinosProperties *props = node->properties;
char *path; char *path;
PinosProtocolDBusNode *obj;
asprintf (&path, "%s_%u", PINOS_DBUS_OBJECT_NODE, global->id); asprintf (&path, "%s_%u", PINOS_DBUS_OBJECT_NODE, global->id);
skel = pinos_object_skeleton_new (path); skel = pinos_object_skeleton_new (path);
@ -565,13 +562,14 @@ on_global_added (PinosListener *listener,
pinos_node1_set_properties (iface, props ? pinos_properties_to_variant (props) : NULL); pinos_node1_set_properties (iface, props ? pinos_properties_to_variant (props) : NULL);
pinos_object_skeleton_set_node1 (skel, iface); pinos_object_skeleton_set_node1 (skel, iface);
object_new (sizeof (PinosProtocolDBusNode), obj = object_new (sizeof (PinosProtocolDBusNode),
impl, impl,
global, global,
iface, iface,
skel, skel,
true, true,
NULL); NULL);
pinos_signal_add (&node->state_changed, &obj->state_changed, on_node_state_changed);
} }
else if (global->object == impl) { else if (global->object == impl) {
PinosProtocolDBus *proto = global->object; PinosProtocolDBus *proto = global->object;
@ -681,7 +679,6 @@ pinos_protocol_dbus_new (PinosCore *core,
pinos_signal_add (&core->global_added, &impl->global_added, on_global_added); 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->global_removed, &impl->global_removed, on_global_removed);
pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed);
impl->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX); impl->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX);

View file

@ -32,17 +32,17 @@ typedef struct {
PinosListener global_added; PinosListener global_added;
PinosListener global_removed; PinosListener global_removed;
PinosListener node_state_request;
PinosListener node_state_changed;
SpaList node_list; SpaList node_list;
} ModuleImpl; } ModuleImpl;
typedef struct { typedef struct {
ModuleImpl *impl; ModuleImpl *impl;
PinosNode *node; PinosNode *node;
SpaList link; SpaList link;
SpaSource *idle_timeout; PinosListener node_state_request;
PinosListener node_state_changed;
SpaSource *idle_timeout;
} NodeInfo; } NodeInfo;
static NodeInfo * static NodeInfo *
@ -66,6 +66,16 @@ remove_idle_timeout (NodeInfo *info)
} }
} }
static void
node_info_free (NodeInfo *info)
{
spa_list_remove (&info->link);
remove_idle_timeout (info);
pinos_signal_remove (&info->node_state_request);
pinos_signal_remove (&info->node_state_changed);
free (info);
}
static void static void
idle_timeout (SpaSource *source, idle_timeout (SpaSource *source,
void *data) void *data)
@ -82,12 +92,7 @@ on_node_state_request (PinosListener *listener,
PinosNode *node, PinosNode *node,
PinosNodeState state) PinosNodeState state)
{ {
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, node_state_changed); NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, node_state_request);
NodeInfo *info;
if ((info = find_node_info (impl, node)) == NULL)
return;
remove_idle_timeout (info); remove_idle_timeout (info);
} }
@ -97,11 +102,8 @@ on_node_state_changed (PinosListener *listener,
PinosNodeState old, PinosNodeState old,
PinosNodeState state) PinosNodeState state)
{ {
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, node_state_changed); NodeInfo *info = SPA_CONTAINER_OF (listener, NodeInfo, node_state_changed);
NodeInfo *info; ModuleImpl *impl = info->impl;
if ((info = find_node_info (impl, node)) == NULL)
return;
if (state != PINOS_NODE_STATE_IDLE) { if (state != PINOS_NODE_STATE_IDLE) {
remove_idle_timeout (info); remove_idle_timeout (info);
@ -137,6 +139,10 @@ on_global_added (PinosListener *listener,
info->impl = impl; info->impl = impl;
info->node = node; info->node = node;
spa_list_insert (impl->node_list.prev, &info->link); spa_list_insert (impl->node_list.prev, &info->link);
pinos_signal_add (&node->state_request, &info->node_state_request, on_node_state_request);
pinos_signal_add (&node->state_changed, &info->node_state_changed, on_node_state_changed);
pinos_log_debug ("module %p: node %p added", impl, node);
} }
} }
@ -151,11 +157,10 @@ on_global_removed (PinosListener *listener,
PinosNode *node = global->object; PinosNode *node = global->object;
NodeInfo *info; NodeInfo *info;
if ((info = find_node_info (impl, node))) { if ((info = find_node_info (impl, node)))
remove_idle_timeout (info); node_info_free (info);
spa_list_remove (&info->link);
free (info); pinos_log_debug ("module %p: node %p removed", impl, node);
}
} }
} }
@ -185,8 +190,6 @@ module_new (PinosCore *core,
pinos_signal_add (&core->global_added, &impl->global_added, on_global_added); 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->global_removed, &impl->global_removed, on_global_removed);
pinos_signal_add (&core->node_state_request, &impl->node_state_request, on_node_state_request);
pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed);
return impl; return impl;
} }
@ -199,7 +202,6 @@ module_destroy (ModuleImpl *impl)
pinos_global_destroy (impl->global); pinos_global_destroy (impl->global);
pinos_signal_remove (&impl->node_state_changed);
free (impl); free (impl);
} }
#endif #endif

View file

@ -196,10 +196,11 @@ spa_proxy_node_send_command (SpaNode *node,
/* send start */ /* send start */
cnc.seq = this->seq++; cnc.seq = this->seq++;
cnc.command = command; cnc.command = command;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_NODE_COMMAND, this->resource,
&cnc, PINOS_MESSAGE_NODE_COMMAND,
true); &cnc,
true);
if (command->type == SPA_NODE_COMMAND_START) { if (command->type == SPA_NODE_COMMAND_START) {
uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA; uint8_t cmd = PINOS_TRANSPORT_CMD_NEED_DATA;
write (this->data_source.fd, &cmd, 1); write (this->data_source.fd, &cmd, 1);
@ -214,10 +215,11 @@ spa_proxy_node_send_command (SpaNode *node,
/* send start */ /* send start */
cnc.command = command; cnc.command = command;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_NODE_COMMAND, this->resource,
&cnc, PINOS_MESSAGE_NODE_COMMAND,
true); &cnc,
true);
break; break;
} }
} }
@ -498,10 +500,11 @@ spa_proxy_node_port_set_format (SpaNode *node,
sf.port_id = port_id; sf.port_id = port_id;
sf.flags = flags; sf.flags = flags;
sf.format = (SpaFormat *) format; sf.format = (SpaFormat *) format;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_SET_FORMAT, this->resource,
&sf, PINOS_MESSAGE_SET_FORMAT,
true); &sf,
true);
return SPA_RESULT_RETURN_ASYNC (sf.seq); return SPA_RESULT_RETURN_ASYNC (sf.seq);
} }
@ -680,10 +683,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.flags = msh->flags; am.flags = msh->flags;
am.offset = msh->offset; am.offset = msh->offset;
am.size = msh->size; am.size = msh->size;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_ADD_MEM, this->resource,
&am, PINOS_MESSAGE_ADD_MEM,
false); &am,
false);
mb[i].buffer = &b->buffer; mb[i].buffer = &b->buffer;
mb[i].mem_id = am.mem_id; mb[i].mem_id = am.mem_id;
@ -710,10 +714,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.flags = d->flags; am.flags = d->flags;
am.offset = d->mapoffset; am.offset = d->mapoffset;
am.size = d->maxsize; am.size = d->maxsize;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_ADD_MEM, this->resource,
&am, PINOS_MESSAGE_ADD_MEM,
false); &am,
false);
b->buffer.datas[j].type = SPA_DATA_TYPE_ID; b->buffer.datas[j].type = SPA_DATA_TYPE_ID;
b->buffer.datas[j].data = SPA_UINT32_TO_PTR (n_mem); b->buffer.datas[j].data = SPA_UINT32_TO_PTR (n_mem);
n_mem++; n_mem++;
@ -736,10 +741,11 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
ub.port_id = port_id; ub.port_id = port_id;
ub.n_buffers = n_buffers; ub.n_buffers = n_buffers;
ub.buffers = mb; ub.buffers = mb;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_USE_BUFFERS, this->resource,
&ub, PINOS_MESSAGE_USE_BUFFERS,
true); &ub,
true);
return SPA_RESULT_RETURN_ASYNC (ub.seq); return SPA_RESULT_RETURN_ASYNC (ub.seq);
} }
@ -772,10 +778,10 @@ spa_proxy_node_port_alloc_buffers (SpaNode *node,
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
#if 0
static void static void
copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id) copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
{ {
#if 0
ProxyBuffer *b = &port->buffers[buffer_id]; ProxyBuffer *b = &port->buffers[buffer_id];
unsigned int i; unsigned int i;
@ -791,13 +797,13 @@ copy_meta_in (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
memcpy (b->outbuf->datas[i].data, b->datas[i].data, b->buffer.datas[i].size); memcpy (b->outbuf->datas[i].data, b->datas[i].data, b->buffer.datas[i].size);
} }
} }
#endif
} }
#endif
#if 0
static void static void
copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id) copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
{ {
#if 0
ProxyBuffer *b = &port->buffers[buffer_id]; ProxyBuffer *b = &port->buffers[buffer_id];
unsigned int i; unsigned int i;
@ -813,8 +819,8 @@ copy_meta_out (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
memcpy (b->datas[i].data, b->outbuf->datas[i].data, b->outbuf->datas[i].size); memcpy (b->datas[i].data, b->outbuf->datas[i].data, b->outbuf->datas[i].size);
} }
} }
#endif
} }
#endif
static SpaResult static SpaResult
spa_proxy_node_port_reuse_buffer (SpaNode *node, spa_proxy_node_port_reuse_buffer (SpaNode *node,
@ -840,6 +846,7 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node,
rb.port_id = port_id; rb.port_id = port_id;
rb.buffer_id = buffer_id; rb.buffer_id = buffer_id;
pinos_transport_add_event (pnode->transport, &rb.event); pinos_transport_add_event (pnode->transport, &rb.event);
cmd = PINOS_TRANSPORT_CMD_HAVE_EVENT; cmd = PINOS_TRANSPORT_CMD_HAVE_EVENT;
write (this->data_source.fd, &cmd, 1); write (this->data_source.fd, &cmd, 1);
@ -1074,7 +1081,8 @@ proxy_on_data_fd_events (SpaSource *source)
if (source->rmask & SPA_IO_IN) { if (source->rmask & SPA_IO_IN) {
uint8_t cmd; uint8_t cmd;
read (this->data_source.fd, &cmd, 1); if (read (this->data_source.fd, &cmd, 1) < 1)
return;
if (cmd & PINOS_TRANSPORT_CMD_HAVE_EVENT) { if (cmd & PINOS_TRANSPORT_CMD_HAVE_EVENT) {
SpaNodeEvent event; SpaNodeEvent event;
@ -1086,17 +1094,6 @@ proxy_on_data_fd_events (SpaSource *source)
} }
if (cmd & PINOS_TRANSPORT_CMD_HAVE_DATA) { if (cmd & PINOS_TRANSPORT_CMD_HAVE_DATA) {
SpaNodeEventHaveOutput ho; SpaNodeEventHaveOutput ho;
unsigned int i;
for (i = 0; i < this->n_outputs; i++) {
SpaProxyPort *port = &this->out_ports[i];
SpaPortOutput *output;
if ((output = port->io) == NULL)
continue;
copy_meta_in (this, port, output->buffer_id);
}
ho.event.type = SPA_NODE_EVENT_TYPE_HAVE_OUTPUT; ho.event.type = SPA_NODE_EVENT_TYPE_HAVE_OUTPUT;
ho.event.size = sizeof (ho); ho.event.size = sizeof (ho);
ho.port_id = 0; ho.port_id = 0;
@ -1191,10 +1188,11 @@ on_transport_changed (PinosListener *listener,
tu.memfd = info.memfd; tu.memfd = info.memfd;
tu.offset = info.offset; tu.offset = info.offset;
tu.size = info.size; tu.size = info.size;
pinos_resource_send_message (this->resource, pinos_client_send_message (this->resource->client,
PINOS_MESSAGE_TRANSPORT_UPDATE, this->resource,
&tu, PINOS_MESSAGE_TRANSPORT_UPDATE,
true); &tu,
true);
} }
static void static void
@ -1379,7 +1377,7 @@ pinos_client_node_get_data_socket (PinosClientNode *this,
if (impl->data_fd == -1) { if (impl->data_fd == -1) {
int fd[2]; int fd[2];
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fd) != 0) if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, fd) != 0)
return SPA_RESULT_ERRNO; return SPA_RESULT_ERRNO;
impl->proxy.data_source.fd = fd[0]; impl->proxy.data_source.fd = fd[0];

View file

@ -88,14 +88,16 @@ client_bind_func (PinosGlobal *global,
info.change_mask = ~0; info.change_mask = ~0;
info.props = this->properties ? &this->properties->dict : NULL; info.props = this->properties ? &this->properties->dict : NULL;
return pinos_resource_send_message (resource, return pinos_client_send_message (client,
PINOS_MESSAGE_CLIENT_INFO, resource,
&m, PINOS_MESSAGE_CLIENT_INFO,
true); &m,
true);
no_mem: no_mem:
pinos_resource_send_error (client->core_resource, pinos_client_send_error (client,
SPA_RESULT_NO_MEMORY, client->core_resource,
"no memory"); SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -129,6 +131,8 @@ pinos_client_new (PinosCore *core,
this->properties = properties; this->properties = properties;
spa_list_init (&this->resource_list); spa_list_init (&this->resource_list);
pinos_signal_init (&this->resource_added);
pinos_signal_init (&this->resource_removed);
pinos_map_init (&this->objects, 64); pinos_map_init (&this->objects, 64);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
@ -203,13 +207,15 @@ do_send_message (PinosAccessData *data)
if (data->res == SPA_RESULT_SKIPPED) { if (data->res == SPA_RESULT_SKIPPED) {
data->res = SPA_RESULT_OK; data->res = SPA_RESULT_OK;
} else if (data->res == SPA_RESULT_NO_PERMISSION) { } else if (data->res == SPA_RESULT_NO_PERMISSION) {
pinos_resource_send_error (data->resource, pinos_client_send_error (data->client,
data->res, data->resource,
"no permission"); data->res,
"no permission");
} else if (SPA_RESULT_IS_ERROR (data->res)) { } else if (SPA_RESULT_IS_ERROR (data->res)) {
pinos_resource_send_error (data->resource, pinos_client_send_error (data->client,
data->res, data->resource,
"error %d", data->res); data->res,
"error %d", data->res);
} else { } else {
data->res = impl->send_func (data->resource, data->res = impl->send_func (data->resource,
data->resource->id, data->resource->id,
@ -255,6 +261,33 @@ pinos_client_send_message (PinosClient *client,
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
SpaResult
pinos_client_send_error (PinosClient *client,
PinosResource *resource,
SpaResult res,
const char *message,
...)
{
PinosMessageError m;
char buffer[128];
va_list ap;
va_start (ap, message);
vsnprintf (buffer, sizeof (buffer), message, ap);
va_end (ap);
m.id = resource->id;
m.res = res;
m.error = buffer;
pinos_log_error ("client %p: %u send error %d (%s)", client, resource->id, res, buffer);
return pinos_client_send_message (client,
client->core_resource,
PINOS_MESSAGE_ERROR,
&m,
true);
}
void void
pinos_client_update_properties (PinosClient *client, pinos_client_update_properties (PinosClient *client,
@ -282,9 +315,10 @@ pinos_client_update_properties (PinosClient *client,
info.props = client->properties ? &client->properties->dict : NULL; info.props = client->properties ? &client->properties->dict : NULL;
spa_list_for_each (resource, &client->resource_list, link) { spa_list_for_each (resource, &client->resource_list, link) {
pinos_resource_send_message (resource, pinos_client_send_message (client,
PINOS_MESSAGE_CLIENT_INFO, resource,
&m, PINOS_MESSAGE_CLIENT_INFO,
true); &m,
true);
} }
} }

View file

@ -60,6 +60,12 @@ struct _PinosClient {
PinosMap objects; PinosMap objects;
SpaList resource_list; SpaList resource_list;
PINOS_SIGNAL (resource_added, (PinosListener *listener,
PinosClient *client,
PinosResource *resource));
PINOS_SIGNAL (resource_removed, (PinosListener *listener,
PinosClient *client,
PinosResource *resource));
PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PINOS_SIGNAL (destroy_signal, (PinosListener *listener,
PinosClient *client)); PinosClient *client));
@ -80,6 +86,11 @@ SpaResult pinos_client_send_message (PinosClient *client,
void *message, void *message,
bool flush); bool flush);
SpaResult pinos_client_send_error (PinosClient *client,
PinosResource *resource,
SpaResult res,
const char *message, ...);
void pinos_client_update_properties (PinosClient *client, void pinos_client_update_properties (PinosClient *client,
const SpaDict *dict); const SpaDict *dict);

View file

@ -57,9 +57,10 @@ registry_dispatch_func (void *object,
break; break;
if (&global->link == &this->global_list) { if (&global->link == &this->global_list) {
pinos_resource_send_error (resource, pinos_client_send_error (client,
SPA_RESULT_INVALID_OBJECT_ID, resource,
"unknown object id %u", m->id); SPA_RESULT_INVALID_OBJECT_ID,
"unknown object id %u", m->id);
return SPA_RESULT_ERROR; return SPA_RESULT_ERROR;
} }
pinos_log_debug ("global %p: bind object id %d", global, m->id); pinos_log_debug ("global %p: bind object id %d", global, m->id);
@ -127,16 +128,18 @@ core_dispatch_func (void *object,
ng.id = global->id; ng.id = global->id;
ng.type = spa_id_map_get_uri (this->uri.map, global->type); ng.type = spa_id_map_get_uri (this->uri.map, global->type);
pinos_resource_send_message (registry_resource, pinos_client_send_message (client,
PINOS_MESSAGE_NOTIFY_GLOBAL, registry_resource,
&ng, PINOS_MESSAGE_NOTIFY_GLOBAL,
false); &ng,
false);
} }
nd.seq = m->seq; nd.seq = m->seq;
pinos_resource_send_message (client->core_resource, pinos_client_send_message (client,
PINOS_MESSAGE_NOTIFY_DONE, client->core_resource,
&nd, PINOS_MESSAGE_NOTIFY_DONE,
true); &nd,
true);
break; break;
} }
case PINOS_MESSAGE_CREATE_CLIENT_NODE: case PINOS_MESSAGE_CREATE_CLIENT_NODE:
@ -165,18 +168,20 @@ core_dispatch_func (void *object,
goto no_mem; goto no_mem;
if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) { if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) {
pinos_resource_send_error (resource, pinos_client_send_error (client,
SPA_RESULT_ERROR, resource,
"can't get data fd"); SPA_RESULT_ERROR,
"can't get data fd");
break; break;
} }
r.seq = m->seq; r.seq = m->seq;
r.datafd = data_fd; r.datafd = data_fd;
pinos_resource_send_message (node->resource, pinos_client_send_message (client,
PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, node->resource,
&r, PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE,
true); &r,
true);
break; break;
} }
default: default:
@ -186,9 +191,10 @@ core_dispatch_func (void *object,
return SPA_RESULT_OK; return SPA_RESULT_OK;
no_mem: no_mem:
pinos_resource_send_error (resource, pinos_client_send_error (client,
SPA_RESULT_NO_MEMORY, resource,
"no memory"); SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -237,10 +243,11 @@ core_bind_func (PinosGlobal *global,
info.cookie = random (); info.cookie = random ();
info.props = NULL; info.props = NULL;
return pinos_resource_send_message (resource, return pinos_client_send_message (resource->client,
PINOS_MESSAGE_CORE_INFO, resource,
&m, PINOS_MESSAGE_CORE_INFO,
true); &m,
true);
no_mem: no_mem:
pinos_log_error ("can't create core resource"); pinos_log_error ("can't create core resource");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
@ -289,14 +296,6 @@ pinos_core_new (PinosMainLoop *main_loop)
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->global_added); pinos_signal_init (&this->global_added);
pinos_signal_init (&this->global_removed); pinos_signal_init (&this->global_removed);
pinos_signal_init (&this->node_state_request);
pinos_signal_init (&this->node_state_changed);
pinos_signal_init (&this->port_added);
pinos_signal_init (&this->port_removed);
pinos_signal_init (&this->port_unlinked);
pinos_signal_init (&this->link_state_changed);
pinos_signal_init (&this->node_unlink);
pinos_signal_init (&this->node_unlink_done);
this->global = pinos_core_add_global (this, this->global = pinos_core_add_global (this,
NULL, NULL,
@ -367,10 +366,11 @@ pinos_core_add_global (PinosCore *core,
pinos_log_debug ("global %p: new %u %s", this, ng.id, ng.type); pinos_log_debug ("global %p: new %u %s", this, ng.id, ng.type);
spa_list_for_each (registry, &core->registry_resource_list, link) { spa_list_for_each (registry, &core->registry_resource_list, link) {
pinos_resource_send_message (registry, pinos_client_send_message (registry->client,
PINOS_MESSAGE_NOTIFY_GLOBAL, registry,
&ng, PINOS_MESSAGE_NOTIFY_GLOBAL,
true); &ng,
true);
} }
return this; return this;
} }
@ -389,9 +389,10 @@ pinos_global_bind (PinosGlobal *global,
res = impl->bind (global, client, version, id); res = impl->bind (global, client, version, id);
} else { } else {
res = SPA_RESULT_NOT_IMPLEMENTED; res = SPA_RESULT_NOT_IMPLEMENTED;
pinos_resource_send_error (client->core_resource, pinos_client_send_error (client,
res, client->core_resource,
"can't bind object id %d", id); res,
"can't bind object id %d", id);
} }
return res; return res;
} }
@ -408,10 +409,11 @@ pinos_global_destroy (PinosGlobal *global)
ng.id = global->id; ng.id = global->id;
spa_list_for_each (registry, &core->registry_resource_list, link) { spa_list_for_each (registry, &core->registry_resource_list, link) {
pinos_resource_send_message (registry, pinos_client_send_message (registry->client,
PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE, registry,
&ng, PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE,
true); &ng,
true);
} }
pinos_map_remove (&core->objects, global->id); pinos_map_remove (&core->objects, global->id);

View file

@ -91,30 +91,6 @@ struct _PinosCore {
PINOS_SIGNAL (global_removed, (PinosListener *listener, PINOS_SIGNAL (global_removed, (PinosListener *listener,
PinosCore *core, PinosCore *core,
PinosGlobal *global)); PinosGlobal *global));
PINOS_SIGNAL (node_state_request, (PinosListener *listener,
PinosNode *object,
PinosNodeState state));
PINOS_SIGNAL (node_state_changed, (PinosListener *listener,
PinosNode *object,
PinosNodeState old,
PinosNodeState state));
PINOS_SIGNAL (port_added, (PinosListener *listener,
PinosNode *node,
PinosPort *port));
PINOS_SIGNAL (port_removed, (PinosListener *listener,
PinosNode *node,
PinosPort *port));
PINOS_SIGNAL (port_unlinked, (PinosListener *listener,
PinosLink *link,
PinosPort *port));
PINOS_SIGNAL (link_state_changed, (PinosListener *listener,
PinosLink *link));
PINOS_SIGNAL (node_unlink, (PinosListener *listener,
PinosNode *node));
PINOS_SIGNAL (node_unlink_done, (PinosListener *listener,
PinosNode *node));
}; };
PinosCore * pinos_core_new (PinosMainLoop *main_loop); PinosCore * pinos_core_new (PinosMainLoop *main_loop);

View file

@ -56,9 +56,11 @@ pinos_link_update_state (PinosLink *link,
PinosLinkState state, PinosLinkState state,
char *error) char *error)
{ {
if (state != link->state) { PinosLinkState old = link->state;
if (state != old) {
pinos_log_debug ("link %p: update state %s -> %s", link, pinos_log_debug ("link %p: update state %s -> %s", link,
pinos_link_state_as_string (link->state), pinos_link_state_as_string (old),
pinos_link_state_as_string (state)); pinos_link_state_as_string (state));
link->state = state; link->state = state;
@ -66,7 +68,7 @@ pinos_link_update_state (PinosLink *link,
free (link->error); free (link->error);
link->error = error; link->error = error;
pinos_signal_emit (&link->core->link_state_changed, link); pinos_signal_emit (&link->state_changed, link, old, state);
} }
} }
@ -684,7 +686,7 @@ on_port_destroy (PinosLink *this,
pinos_port_clear_buffers (other); pinos_port_clear_buffers (other);
} }
pinos_signal_emit (&this->core->port_unlinked, this, port); pinos_signal_emit (&this->port_unlinked, this, port);
pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL); pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED, NULL);
pinos_link_destroy (this); pinos_link_destroy (this);
@ -811,14 +813,16 @@ link_bind_func (PinosGlobal *global,
info.input_node_id = this->input ? this->input->node->global->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; info.input_port_id = this->input ? this->input->port_id : -1;
return pinos_resource_send_message (resource, return pinos_client_send_message (resource->client,
PINOS_MESSAGE_LINK_INFO, resource,
&m, PINOS_MESSAGE_LINK_INFO,
true); &m,
true);
no_mem: no_mem:
pinos_resource_send_error (client->core_resource, pinos_client_send_error (client,
SPA_RESULT_NO_MEMORY, client->core_resource,
"no memory"); SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -850,6 +854,8 @@ pinos_link_new (PinosCore *core,
this->output = output; this->output = output;
spa_list_init (&this->resource_list); spa_list_init (&this->resource_list);
pinos_signal_init (&this->port_unlinked);
pinos_signal_init (&this->state_changed);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->free_signal); pinos_signal_init (&this->free_signal);

View file

@ -48,6 +48,10 @@ struct _PinosLink {
PinosLinkState state; PinosLinkState state;
char *error; char *error;
PINOS_SIGNAL (state_changed, (PinosListener *listener,
PinosLink *link,
PinosLinkState old,
PinosLinkState state));
PINOS_SIGNAL (destroy_signal, (PinosListener *, PINOS_SIGNAL (destroy_signal, (PinosListener *,
PinosLink *)); PinosLink *));
@ -60,6 +64,9 @@ struct _PinosLink {
SpaList output_link; SpaList output_link;
PinosPort *input; PinosPort *input;
SpaList input_link; SpaList input_link;
PINOS_SIGNAL (port_unlinked, (PinosListener *listener,
PinosLink *link,
PinosPort *port));
uint32_t queue[64]; uint32_t queue[64];
SpaRingbuffer ringbuffer; SpaRingbuffer ringbuffer;

View file

@ -140,14 +140,16 @@ module_bind_func (PinosGlobal *global,
info.args = this->args; info.args = this->args;
info.props = NULL; info.props = NULL;
return pinos_resource_send_message (resource, return pinos_client_send_message (client,
PINOS_MESSAGE_MODULE_INFO, resource,
&m, PINOS_MESSAGE_MODULE_INFO,
true); &m,
true);
no_mem: no_mem:
pinos_resource_send_error (resource, pinos_client_send_error (client,
SPA_RESULT_NO_MEMORY, client->core_resource,
"no memory"); SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }

View file

@ -92,13 +92,13 @@ update_port_ids (PinosNode *node, bool create)
node->input_port_map[np->port_id] = np; node->input_port_map[np->port_id] = np;
if (!impl->async_init) if (!impl->async_init)
pinos_signal_emit (&node->core->port_added, node, np); pinos_signal_emit (&node->port_added, node, np);
i++; i++;
} else if (p) { } else if (p) {
node->input_port_map[p->port_id] = NULL; node->input_port_map[p->port_id] = NULL;
ports = ports->next; ports = ports->next;
if (!impl->async_init) if (!impl->async_init)
pinos_signal_emit (&node->core->port_removed, node, p); pinos_signal_emit (&node->port_removed, node, p);
pinos_log_debug ("node %p: input port removed %d", node, p->port_id); pinos_log_debug ("node %p: input port removed %d", node, p->port_id);
pinos_port_destroy (p); pinos_port_destroy (p);
} else { } else {
@ -127,13 +127,13 @@ update_port_ids (PinosNode *node, bool create)
node->output_port_map[np->port_id] = np; node->output_port_map[np->port_id] = np;
if (!impl->async_init) if (!impl->async_init)
pinos_signal_emit (&node->core->port_added, node, np); pinos_signal_emit (&node->port_added, node, np);
i++; i++;
} else if (p) { } else if (p) {
node->output_port_map[p->port_id] = NULL; node->output_port_map[p->port_id] = NULL;
ports = ports->next; ports = ports->next;
if (!impl->async_init) if (!impl->async_init)
pinos_signal_emit (&node->core->port_removed, node, p); pinos_signal_emit (&node->port_removed, node, p);
pinos_log_debug ("node %p: output port removed %d", node, p->port_id); pinos_log_debug ("node %p: output port removed %d", node, p->port_id);
pinos_port_destroy (p); pinos_port_destroy (p);
} else { } else {
@ -443,14 +443,16 @@ node_bind_func (PinosGlobal *global,
info.error = this->error; info.error = this->error;
info.props = this->properties ? &this->properties->dict : NULL; info.props = this->properties ? &this->properties->dict : NULL;
return pinos_resource_send_message (resource, return pinos_client_send_message (client,
PINOS_MESSAGE_NODE_INFO, resource,
&m, PINOS_MESSAGE_NODE_INFO,
true); &m,
true);
no_mem: no_mem:
pinos_resource_send_error (resource, pinos_client_send_error (client,
SPA_RESULT_NO_MEMORY, client->core_resource,
"no memory"); SPA_RESULT_NO_MEMORY,
"no memory");
return SPA_RESULT_NO_MEMORY; return SPA_RESULT_NO_MEMORY;
} }
@ -515,6 +517,10 @@ pinos_node_new (PinosCore *core,
pinos_log_warn ("node %p: error setting callback", this); pinos_log_warn ("node %p: error setting callback", this);
pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->port_added);
pinos_signal_init (&this->port_removed);
pinos_signal_init (&this->state_request);
pinos_signal_init (&this->state_changed);
pinos_signal_init (&this->free_signal); pinos_signal_init (&this->free_signal);
pinos_signal_init (&this->async_complete); pinos_signal_init (&this->async_complete);
pinos_signal_init (&this->transport_changed); pinos_signal_init (&this->transport_changed);
@ -747,7 +753,7 @@ pinos_node_set_state (PinosNode *node,
SpaResult res = SPA_RESULT_OK; SpaResult res = SPA_RESULT_OK;
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
pinos_signal_emit (&node->core->node_state_request, node, state); pinos_signal_emit (&node->state_request, node, state);
pinos_log_debug ("node %p: set state %s", node, pinos_node_state_as_string (state)); pinos_log_debug ("node %p: set state %s", node, pinos_node_state_as_string (state));
@ -814,7 +820,7 @@ pinos_node_update_state (PinosNode *node,
node->error = error; node->error = error;
node->state = state; node->state = state;
pinos_signal_emit (&node->core->node_state_changed, node, old, state); pinos_signal_emit (&node->state_changed, node, old, state);
spa_zero (info); spa_zero (info);
m.info = &info; m.info = &info;
@ -824,10 +830,11 @@ pinos_node_update_state (PinosNode *node,
spa_list_for_each (resource, &node->resource_list, link) { spa_list_for_each (resource, &node->resource_list, link) {
info.id = node->global->id; info.id = node->global->id;
pinos_resource_send_message (resource, pinos_client_send_message (resource->client,
PINOS_MESSAGE_NODE_INFO, resource,
&m, PINOS_MESSAGE_NODE_INFO,
true); &m,
true);
} }
} }
} }

View file

@ -56,6 +56,13 @@ struct _PinosNode {
PinosProperties *properties; PinosProperties *properties;
PinosNodeState state; PinosNodeState state;
char *error; char *error;
PINOS_SIGNAL (state_request, (PinosListener *listener,
PinosNode *object,
PinosNodeState state));
PINOS_SIGNAL (state_changed, (PinosListener *listener,
PinosNode *object,
PinosNodeState old,
PinosNodeState state));
SpaHandle *handle; SpaHandle *handle;
SpaNode *node; SpaNode *node;
@ -66,6 +73,12 @@ struct _PinosNode {
SpaList input_ports; SpaList input_ports;
SpaList output_ports; SpaList output_ports;
PINOS_SIGNAL (port_added, (PinosListener *listener,
PinosNode *node,
PinosPort *port));
PINOS_SIGNAL (port_removed, (PinosListener *listener,
PinosNode *node,
PinosPort *port));
PinosPort **input_port_map; PinosPort **input_port_map;
PinosPort **output_port_map; PinosPort **output_port_map;

View file

@ -46,7 +46,6 @@ pinos_resource_new (PinosClient *client,
this->core = client->core; this->core = client->core;
this->client = client; this->client = client;
this->id = id;
this->type = type; this->type = type;
this->object = object; this->object = object;
this->destroy = destroy; this->destroy = destroy;
@ -55,6 +54,7 @@ pinos_resource_new (PinosClient *client,
this->id = pinos_map_insert_new (&client->objects, this); this->id = pinos_map_insert_new (&client->objects, this);
pinos_log_debug ("resource %p: new for client %p id %u", this, client, this->id); pinos_log_debug ("resource %p: new for client %p id %u", this, client, this->id);
pinos_signal_emit (&client->resource_added, client, this);
return this; return this;
} }
@ -62,19 +62,23 @@ pinos_resource_new (PinosClient *client,
void void
pinos_resource_destroy (PinosResource *resource) pinos_resource_destroy (PinosResource *resource)
{ {
PinosClient *client = resource->client;
pinos_log_debug ("resource %p: destroy", resource); pinos_log_debug ("resource %p: destroy", resource);
pinos_signal_emit (&resource->destroy_signal, resource); pinos_signal_emit (&resource->destroy_signal, resource);
if (resource->client->core_resource) { if (client->core_resource) {
PinosMessageRemoveId m; PinosMessageRemoveId m;
m.id = resource->id; m.id = resource->id;
pinos_resource_send_message (resource->client->core_resource, pinos_client_send_message (client,
PINOS_MESSAGE_REMOVE_ID, client->core_resource,
&m, PINOS_MESSAGE_REMOVE_ID,
true); &m,
true);
} }
pinos_map_remove (&resource->client->objects, resource->id); pinos_map_remove (&client->objects, resource->id);
pinos_signal_emit (&client->resource_removed, client, resource);
if (resource->destroy) if (resource->destroy)
resource->destroy (resource); resource->destroy (resource);
@ -100,13 +104,15 @@ do_dispatch_message (PinosAccessData *data)
PinosResourceImpl *impl = SPA_CONTAINER_OF (data->resource, PinosResourceImpl, this); PinosResourceImpl *impl = SPA_CONTAINER_OF (data->resource, PinosResourceImpl, this);
if (data->res == SPA_RESULT_NO_PERMISSION) { if (data->res == SPA_RESULT_NO_PERMISSION) {
pinos_resource_send_error (data->resource, pinos_client_send_error (data->client,
data->res, data->resource,
"no permission"); data->res,
"no permission");
} else if (SPA_RESULT_IS_ERROR (data->res)) { } else if (SPA_RESULT_IS_ERROR (data->res)) {
pinos_resource_send_error (data->resource, pinos_client_send_error (data->client,
data->res, data->resource,
"error %d", data->res); data->res,
"error %d", data->res);
} else { } else {
data->res = impl->dispatch_func (data->resource, data->res = impl->dispatch_func (data->resource,
data->opcode, data->opcode,
@ -147,43 +153,3 @@ pinos_resource_dispatch (PinosResource *resource,
return SPA_RESULT_NOT_IMPLEMENTED; return SPA_RESULT_NOT_IMPLEMENTED;
} }
SpaResult
pinos_resource_send_message (PinosResource *resource,
uint32_t opcode,
void *message,
bool flush)
{
return pinos_client_send_message (resource->client,
resource,
opcode,
message,
flush);
}
SpaResult
pinos_resource_send_error (PinosResource *resource,
SpaResult res,
const char *message,
...)
{
PinosClient *client = resource->client;
PinosMessageError m;
char buffer[128];
va_list ap;
va_start (ap, message);
vsnprintf (buffer, sizeof (buffer), message, ap);
va_end (ap);
m.id = resource->id;
m.res = res;
m.error = buffer;
pinos_log_error ("resource %p: %u send error %d %s", resource, resource->id, res, buffer);
return pinos_resource_send_message (client->core_resource,
PINOS_MESSAGE_ERROR,
&m,
true);
}

View file

@ -72,14 +72,6 @@ SpaResult pinos_resource_dispatch (PinosResource *resource,
uint32_t opcode, uint32_t opcode,
void *message); void *message);
SpaResult pinos_resource_send_message (PinosResource *resource,
uint32_t opcode,
void *message,
bool flush);
SpaResult pinos_resource_send_error (PinosResource *resource,
SpaResult res,
const char *message, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -32,16 +32,16 @@
typedef struct _SpaALSAState SpaALSASink; typedef struct _SpaALSAState SpaALSASink;
static const char default_device[] = "default"; static const char default_device[] = "default";
static const uint32_t default_buffer_time = 4000; static const uint32_t default_period_size = 128;
static const uint32_t default_period_time = 100; static const uint32_t default_periods = 2;
static const bool default_period_event = 0; static const bool default_period_event = 0;
static void static void
reset_alsa_sink_props (SpaALSAProps *props) reset_alsa_sink_props (SpaALSAProps *props)
{ {
strncpy (props->device, default_device, 64); strncpy (props->device, default_device, 64);
props->buffer_time = default_buffer_time; props->period_size = default_period_size;
props->period_time = default_period_time; props->periods = default_periods;
props->period_event = default_period_event; props->period_event = default_period_event;
} }
@ -64,8 +64,8 @@ enum {
PROP_ID_DEVICE, PROP_ID_DEVICE,
PROP_ID_DEVICE_NAME, PROP_ID_DEVICE_NAME,
PROP_ID_CARD_NAME, PROP_ID_CARD_NAME,
PROP_ID_BUFFER_TIME, PROP_ID_PERIOD_SIZE,
PROP_ID_PERIOD_TIME, PROP_ID_PERIODS,
PROP_ID_PERIOD_EVENT, PROP_ID_PERIOD_EVENT,
PROP_ID_LAST, PROP_ID_LAST,
}; };
@ -90,14 +90,14 @@ static const SpaPropInfo prop_info[] =
SPA_PROP_TYPE_STRING, 127, SPA_PROP_TYPE_STRING, 127,
SPA_PROP_RANGE_TYPE_NONE, 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL }, NULL },
{ PROP_ID_BUFFER_TIME, offsetof (SpaALSAProps, buffer_time), { PROP_ID_PERIOD_SIZE, offsetof (SpaALSAProps, period_size),
"buffer-time", "period-size",
SPA_PROP_FLAG_READWRITE, SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
NULL }, NULL },
{ PROP_ID_PERIOD_TIME, offsetof (SpaALSAProps, period_time), { PROP_ID_PERIODS, offsetof (SpaALSAProps, periods),
"period-time", "periods",
SPA_PROP_FLAG_READWRITE, SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,

View file

@ -39,16 +39,16 @@ update_state (SpaALSASource *this, SpaNodeState state)
} }
static const char default_device[] = "hw:0"; static const char default_device[] = "hw:0";
static const uint32_t default_buffer_time = 10000; static const uint32_t default_period_size = 128;
static const uint32_t default_period_time = 1000; static const uint32_t default_periods = 2;
static const bool default_period_event = 0; static const bool default_period_event = 0;
static void static void
reset_alsa_props (SpaALSAProps *props) reset_alsa_props (SpaALSAProps *props)
{ {
strncpy (props->device, default_device, 64); strncpy (props->device, default_device, 64);
props->buffer_time = default_buffer_time; props->period_size = default_period_size;
props->period_time = default_period_time; props->periods = default_periods;
props->period_event = default_period_event; props->period_event = default_period_event;
props->props.unset_mask = 0xf; props->props.unset_mask = 0xf;
} }
@ -65,8 +65,8 @@ enum {
PROP_ID_DEVICE, PROP_ID_DEVICE,
PROP_ID_DEVICE_NAME, PROP_ID_DEVICE_NAME,
PROP_ID_CARD_NAME, PROP_ID_CARD_NAME,
PROP_ID_BUFFER_TIME, PROP_ID_PERIOD_SIZE,
PROP_ID_PERIOD_TIME, PROP_ID_PERIODS,
PROP_ID_PERIOD_EVENT, PROP_ID_PERIOD_EVENT,
PROP_ID_LAST, PROP_ID_LAST,
}; };
@ -91,14 +91,14 @@ static const SpaPropInfo prop_info[] =
SPA_PROP_TYPE_STRING, 127, SPA_PROP_TYPE_STRING, 127,
SPA_PROP_RANGE_TYPE_NONE, 0, NULL, SPA_PROP_RANGE_TYPE_NONE, 0, NULL,
NULL }, NULL },
{ PROP_ID_BUFFER_TIME, offsetof (SpaALSAProps, buffer_time), { PROP_ID_PERIOD_SIZE, offsetof (SpaALSAProps, period_size),
"buffer-time", "period-size",
SPA_PROP_FLAG_READWRITE, SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,
NULL }, NULL },
{ PROP_ID_PERIOD_TIME, offsetof (SpaALSAProps, period_time), { PROP_ID_PERIODS, offsetof (SpaALSAProps, periods),
"period-time", "periods",
SPA_PROP_FLAG_READWRITE, SPA_PROP_FLAG_READWRITE,
SPA_PROP_TYPE_UINT32, sizeof (uint32_t), SPA_PROP_TYPE_UINT32, sizeof (uint32_t),
SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range, SPA_PROP_RANGE_TYPE_MIN_MAX, 2, uint32_range,

View file

@ -111,14 +111,13 @@ int
spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlags flags) spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlags flags)
{ {
unsigned int rrate, rchannels; unsigned int rrate, rchannels;
snd_pcm_uframes_t size; snd_pcm_uframes_t period_size;
int err, dir; int err, dir;
snd_pcm_hw_params_t *params; snd_pcm_hw_params_t *params;
snd_pcm_format_t format; snd_pcm_format_t format;
SpaAudioInfoRaw *info = &fmt->info.raw; SpaAudioInfoRaw *info = &fmt->info.raw;
snd_pcm_t *hndl; snd_pcm_t *hndl;
unsigned int buffer_time; unsigned int periods;
unsigned int period_time;
SpaALSAProps *props = &state->props[1]; SpaALSAProps *props = &state->props[1];
if ((err = spa_alsa_open (state)) < 0) if ((err = spa_alsa_open (state)) < 0)
@ -166,17 +165,31 @@ spa_alsa_set_format (SpaALSAState *state, SpaFormatAudio *fmt, SpaPortFormatFlag
state->rate = info->rate; state->rate = info->rate;
state->frame_size = info->channels * 2; state->frame_size = info->channels * 2;
period_size = props->period_size;
CHECK (snd_pcm_hw_params_set_period_size_near (hndl, params, &period_size, &dir), "set_period_size");
state->period_frames = period_size;
periods = props->periods;
CHECK (snd_pcm_hw_params_set_periods_near (hndl, params, &periods, &dir), "set_periods_near");
state->buffer_frames = periods * state->period_frames;
CHECK (snd_pcm_hw_params_set_buffer_size (hndl, params, state->buffer_frames), "set_buffer_size");
#if 0
/* set the buffer time */ /* set the buffer time */
buffer_time = props->buffer_time; buffer_time = props->buffer_time;
CHECK (snd_pcm_hw_params_set_buffer_time_near (hndl, params, &buffer_time, &dir), "set_buffer_time_near"); CHECK (snd_pcm_hw_params_set_buffer_time_near (hndl, params, &buffer_time, &dir), "set_buffer_time_near");
CHECK (snd_pcm_hw_params_get_buffer_size (params, &size), "get_buffer_size"); CHECK (snd_pcm_hw_params_get_buffer_size (params, &size), "get_buffer_size");
state->buffer_frames = size; state->buffer_frames = size;
/* set the period time */ /* set the period time */
period_time = props->period_time; period_time = props->period_time;
CHECK (snd_pcm_hw_params_set_period_time_near (hndl, params, &period_time, &dir), "set_period_time_near"); CHECK (snd_pcm_hw_params_set_period_time_near (hndl, params, &period_time, &dir), "set_period_time_near");
CHECK (snd_pcm_hw_params_get_period_size (params, &size, &dir), "get_period_size"); CHECK (snd_pcm_hw_params_get_period_size (params, &size, &dir), "get_period_size");
state->period_frames = size; state->period_frames = size;
#endif
spa_log_info (state->log, "buffer frames %zd, period frames %zd", state->buffer_frames, state->period_frames); spa_log_info (state->log, "buffer frames %zd, period frames %zd", state->buffer_frames, state->period_frames);
@ -391,10 +404,12 @@ mmap_write (SpaALSAState *state)
} }
#endif #endif
#if 0
ni.event.type = SPA_NODE_EVENT_TYPE_NEED_INPUT; ni.event.type = SPA_NODE_EVENT_TYPE_NEED_INPUT;
ni.event.size = sizeof (ni); ni.event.size = sizeof (ni);
ni.port_id = 0; ni.port_id = 0;
state->event_cb (&state->node, &ni.event, state->user_data); state->event_cb (&state->node, &ni.event, state->user_data);
#endif
size = avail; size = avail;
while (size > 0) { while (size > 0) {
@ -536,7 +551,6 @@ alsa_on_fd_events (SpaSource *source)
if (revents & SPA_IO_ERR) { if (revents & SPA_IO_ERR) {
if ((err = xrun_recovery (state, hndl, err)) < 0) { if ((err = xrun_recovery (state, hndl, err)) < 0) {
spa_log_error (state->log, "error: %s", snd_strerror (err)); spa_log_error (state->log, "error: %s", snd_strerror (err));
return;
} }
} }

View file

@ -44,8 +44,8 @@ typedef struct {
char device[64]; char device[64];
char device_name[128]; char device_name[128];
char card_name[128]; char card_name[128];
uint32_t buffer_time; uint32_t period_size;
uint32_t period_time; uint32_t periods;
bool period_event; bool period_event;
} SpaALSAProps; } SpaALSAProps;