mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									fb69758251
								
							
						
					
					
						commit
						cae971e106
					
				
					 23 changed files with 573 additions and 384 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SpaList node_list;
 | 
				
			||||||
 | 
					  SpaList client_list;
 | 
				
			||||||
 | 
					} ModuleImpl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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_added;
 | 
				
			||||||
  PinosListener  port_removed;
 | 
					  PinosListener  port_removed;
 | 
				
			||||||
  PinosListener  port_unlinked;
 | 
					  PinosListener  port_unlinked;
 | 
				
			||||||
  PinosListener  link_state_changed;
 | 
					  PinosListener  link_state_changed;
 | 
				
			||||||
} ModuleImpl;
 | 
					} 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
 | 
					static void
 | 
				
			||||||
try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
 | 
					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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,8 +32,6 @@ 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;
 | 
				
			||||||
| 
						 | 
					@ -42,6 +40,8 @@ typedef struct {
 | 
				
			||||||
  ModuleImpl    *impl;
 | 
					  ModuleImpl    *impl;
 | 
				
			||||||
  PinosNode     *node;
 | 
					  PinosNode     *node;
 | 
				
			||||||
  SpaList        link;
 | 
					  SpaList        link;
 | 
				
			||||||
 | 
					  PinosListener  node_state_request;
 | 
				
			||||||
 | 
					  PinosListener  node_state_changed;
 | 
				
			||||||
  SpaSource     *idle_timeout;
 | 
					  SpaSource     *idle_timeout;
 | 
				
			||||||
} NodeInfo;
 | 
					} 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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -196,7 +196,8 @@ 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,
 | 
				
			||||||
 | 
					                                 this->resource,
 | 
				
			||||||
                                 PINOS_MESSAGE_NODE_COMMAND,
 | 
					                                 PINOS_MESSAGE_NODE_COMMAND,
 | 
				
			||||||
                                 &cnc,
 | 
					                                 &cnc,
 | 
				
			||||||
                                 true);
 | 
					                                 true);
 | 
				
			||||||
| 
						 | 
					@ -214,7 +215,8 @@ 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,
 | 
				
			||||||
 | 
					                                 this->resource,
 | 
				
			||||||
                                 PINOS_MESSAGE_NODE_COMMAND,
 | 
					                                 PINOS_MESSAGE_NODE_COMMAND,
 | 
				
			||||||
                                 &cnc,
 | 
					                                 &cnc,
 | 
				
			||||||
                                 true);
 | 
					                                 true);
 | 
				
			||||||
| 
						 | 
					@ -498,7 +500,8 @@ 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,
 | 
				
			||||||
 | 
					                             this->resource,
 | 
				
			||||||
                             PINOS_MESSAGE_SET_FORMAT,
 | 
					                             PINOS_MESSAGE_SET_FORMAT,
 | 
				
			||||||
                             &sf,
 | 
					                             &sf,
 | 
				
			||||||
                             true);
 | 
					                             true);
 | 
				
			||||||
| 
						 | 
					@ -680,7 +683,8 @@ 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,
 | 
				
			||||||
 | 
					                               this->resource,
 | 
				
			||||||
                               PINOS_MESSAGE_ADD_MEM,
 | 
					                               PINOS_MESSAGE_ADD_MEM,
 | 
				
			||||||
                               &am,
 | 
					                               &am,
 | 
				
			||||||
                               false);
 | 
					                               false);
 | 
				
			||||||
| 
						 | 
					@ -710,7 +714,8 @@ 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,
 | 
				
			||||||
 | 
					                                     this->resource,
 | 
				
			||||||
                                     PINOS_MESSAGE_ADD_MEM,
 | 
					                                     PINOS_MESSAGE_ADD_MEM,
 | 
				
			||||||
                                     &am,
 | 
					                                     &am,
 | 
				
			||||||
                                     false);
 | 
					                                     false);
 | 
				
			||||||
| 
						 | 
					@ -736,7 +741,8 @@ 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,
 | 
				
			||||||
 | 
					                             this->resource,
 | 
				
			||||||
                             PINOS_MESSAGE_USE_BUFFERS,
 | 
					                             PINOS_MESSAGE_USE_BUFFERS,
 | 
				
			||||||
                             &ub,
 | 
					                             &ub,
 | 
				
			||||||
                             true);
 | 
					                             true);
 | 
				
			||||||
| 
						 | 
					@ -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,7 +1188,8 @@ 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,
 | 
				
			||||||
 | 
					                             this->resource,
 | 
				
			||||||
                             PINOS_MESSAGE_TRANSPORT_UPDATE,
 | 
					                             PINOS_MESSAGE_TRANSPORT_UPDATE,
 | 
				
			||||||
                             &tu,
 | 
					                             &tu,
 | 
				
			||||||
                             true);
 | 
					                             true);
 | 
				
			||||||
| 
						 | 
					@ -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];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,12 +88,14 @@ 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,
 | 
				
			||||||
 | 
					                                    resource,
 | 
				
			||||||
                                    PINOS_MESSAGE_CLIENT_INFO,
 | 
					                                    PINOS_MESSAGE_CLIENT_INFO,
 | 
				
			||||||
                                    &m,
 | 
					                                    &m,
 | 
				
			||||||
                                    true);
 | 
					                                    true);
 | 
				
			||||||
no_mem:
 | 
					no_mem:
 | 
				
			||||||
  pinos_resource_send_error (client->core_resource,
 | 
					  pinos_client_send_error (client,
 | 
				
			||||||
 | 
					                           client->core_resource,
 | 
				
			||||||
                           SPA_RESULT_NO_MEMORY,
 | 
					                           SPA_RESULT_NO_MEMORY,
 | 
				
			||||||
                           "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,11 +207,13 @@ 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->resource,
 | 
				
			||||||
                             data->res,
 | 
					                             data->res,
 | 
				
			||||||
                             "no permission");
 | 
					                             "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->resource,
 | 
				
			||||||
                             data->res,
 | 
					                             data->res,
 | 
				
			||||||
                             "error %d", data->res);
 | 
					                             "error %d", data->res);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
| 
						 | 
					@ -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,7 +315,8 @@ 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,
 | 
				
			||||||
 | 
					                               resource,
 | 
				
			||||||
                               PINOS_MESSAGE_CLIENT_INFO,
 | 
					                               PINOS_MESSAGE_CLIENT_INFO,
 | 
				
			||||||
                               &m,
 | 
					                               &m,
 | 
				
			||||||
                               true);
 | 
					                               true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,8 @@ 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,
 | 
				
			||||||
 | 
					                                 resource,
 | 
				
			||||||
                                 SPA_RESULT_INVALID_OBJECT_ID,
 | 
					                                 SPA_RESULT_INVALID_OBJECT_ID,
 | 
				
			||||||
                                 "unknown object id %u", m->id);
 | 
					                                 "unknown object id %u", m->id);
 | 
				
			||||||
        return SPA_RESULT_ERROR;
 | 
					        return SPA_RESULT_ERROR;
 | 
				
			||||||
| 
						 | 
					@ -127,13 +128,15 @@ 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,
 | 
				
			||||||
 | 
					                                   registry_resource,
 | 
				
			||||||
                                   PINOS_MESSAGE_NOTIFY_GLOBAL,
 | 
					                                   PINOS_MESSAGE_NOTIFY_GLOBAL,
 | 
				
			||||||
                                   &ng,
 | 
					                                   &ng,
 | 
				
			||||||
                                   false);
 | 
					                                   false);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      nd.seq = m->seq;
 | 
					      nd.seq = m->seq;
 | 
				
			||||||
      pinos_resource_send_message (client->core_resource,
 | 
					      pinos_client_send_message (client,
 | 
				
			||||||
 | 
					                                 client->core_resource,
 | 
				
			||||||
                                 PINOS_MESSAGE_NOTIFY_DONE,
 | 
					                                 PINOS_MESSAGE_NOTIFY_DONE,
 | 
				
			||||||
                                 &nd,
 | 
					                                 &nd,
 | 
				
			||||||
                                 true);
 | 
					                                 true);
 | 
				
			||||||
| 
						 | 
					@ -165,7 +168,8 @@ 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,
 | 
				
			||||||
 | 
					                                 resource,
 | 
				
			||||||
                                 SPA_RESULT_ERROR,
 | 
					                                 SPA_RESULT_ERROR,
 | 
				
			||||||
                                 "can't get data fd");
 | 
					                                 "can't get data fd");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
| 
						 | 
					@ -173,7 +177,8 @@ core_dispatch_func (void             *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      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,
 | 
				
			||||||
 | 
					                                 node->resource,
 | 
				
			||||||
                                 PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE,
 | 
					                                 PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE,
 | 
				
			||||||
                                 &r,
 | 
					                                 &r,
 | 
				
			||||||
                                 true);
 | 
					                                 true);
 | 
				
			||||||
| 
						 | 
					@ -186,7 +191,8 @@ 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,
 | 
				
			||||||
 | 
					                           resource,
 | 
				
			||||||
                           SPA_RESULT_NO_MEMORY,
 | 
					                           SPA_RESULT_NO_MEMORY,
 | 
				
			||||||
                           "no memory");
 | 
					                           "no memory");
 | 
				
			||||||
  return SPA_RESULT_NO_MEMORY;
 | 
					  return SPA_RESULT_NO_MEMORY;
 | 
				
			||||||
| 
						 | 
					@ -237,7 +243,8 @@ 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,
 | 
				
			||||||
 | 
					                                    resource,
 | 
				
			||||||
                                    PINOS_MESSAGE_CORE_INFO,
 | 
					                                    PINOS_MESSAGE_CORE_INFO,
 | 
				
			||||||
                                    &m,
 | 
					                                    &m,
 | 
				
			||||||
                                    true);
 | 
					                                    true);
 | 
				
			||||||
| 
						 | 
					@ -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,7 +366,8 @@ 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,
 | 
				
			||||||
 | 
					                               registry,
 | 
				
			||||||
                               PINOS_MESSAGE_NOTIFY_GLOBAL,
 | 
					                               PINOS_MESSAGE_NOTIFY_GLOBAL,
 | 
				
			||||||
                               &ng,
 | 
					                               &ng,
 | 
				
			||||||
                               true);
 | 
					                               true);
 | 
				
			||||||
| 
						 | 
					@ -389,7 +389,8 @@ 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,
 | 
				
			||||||
 | 
					                             client->core_resource,
 | 
				
			||||||
                             res,
 | 
					                             res,
 | 
				
			||||||
                             "can't bind object id %d", id);
 | 
					                             "can't bind object id %d", id);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -408,7 +409,8 @@ 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,
 | 
				
			||||||
 | 
					                               registry,
 | 
				
			||||||
                               PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE,
 | 
					                               PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE,
 | 
				
			||||||
                               &ng,
 | 
					                               &ng,
 | 
				
			||||||
                               true);
 | 
					                               true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,12 +813,14 @@ 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,
 | 
				
			||||||
 | 
					                                    resource,
 | 
				
			||||||
                                    PINOS_MESSAGE_LINK_INFO,
 | 
					                                    PINOS_MESSAGE_LINK_INFO,
 | 
				
			||||||
                                    &m,
 | 
					                                    &m,
 | 
				
			||||||
                                    true);
 | 
					                                    true);
 | 
				
			||||||
no_mem:
 | 
					no_mem:
 | 
				
			||||||
  pinos_resource_send_error (client->core_resource,
 | 
					  pinos_client_send_error (client,
 | 
				
			||||||
 | 
					                           client->core_resource,
 | 
				
			||||||
                           SPA_RESULT_NO_MEMORY,
 | 
					                           SPA_RESULT_NO_MEMORY,
 | 
				
			||||||
                           "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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,12 +140,14 @@ 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,
 | 
				
			||||||
 | 
					                                    resource,
 | 
				
			||||||
                                    PINOS_MESSAGE_MODULE_INFO,
 | 
					                                    PINOS_MESSAGE_MODULE_INFO,
 | 
				
			||||||
                                    &m,
 | 
					                                    &m,
 | 
				
			||||||
                                    true);
 | 
					                                    true);
 | 
				
			||||||
no_mem:
 | 
					no_mem:
 | 
				
			||||||
  pinos_resource_send_error (resource,
 | 
					  pinos_client_send_error (client,
 | 
				
			||||||
 | 
					                           client->core_resource,
 | 
				
			||||||
                           SPA_RESULT_NO_MEMORY,
 | 
					                           SPA_RESULT_NO_MEMORY,
 | 
				
			||||||
                           "no memory");
 | 
					                           "no memory");
 | 
				
			||||||
  return SPA_RESULT_NO_MEMORY;
 | 
					  return SPA_RESULT_NO_MEMORY;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,12 +443,14 @@ 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,
 | 
				
			||||||
 | 
					                                    resource,
 | 
				
			||||||
                                    PINOS_MESSAGE_NODE_INFO,
 | 
					                                    PINOS_MESSAGE_NODE_INFO,
 | 
				
			||||||
                                    &m,
 | 
					                                    &m,
 | 
				
			||||||
                                    true);
 | 
					                                    true);
 | 
				
			||||||
no_mem:
 | 
					no_mem:
 | 
				
			||||||
  pinos_resource_send_error (resource,
 | 
					  pinos_client_send_error (client,
 | 
				
			||||||
 | 
					                           client->core_resource,
 | 
				
			||||||
                           SPA_RESULT_NO_MEMORY,
 | 
					                           SPA_RESULT_NO_MEMORY,
 | 
				
			||||||
                           "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,7 +830,8 @@ 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,
 | 
				
			||||||
 | 
					                                 resource,
 | 
				
			||||||
                                 PINOS_MESSAGE_NODE_INFO,
 | 
					                                 PINOS_MESSAGE_NODE_INFO,
 | 
				
			||||||
                                 &m,
 | 
					                                 &m,
 | 
				
			||||||
                                 true);
 | 
					                                 true);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
 | 
					                               client->core_resource,
 | 
				
			||||||
                               PINOS_MESSAGE_REMOVE_ID,
 | 
					                               PINOS_MESSAGE_REMOVE_ID,
 | 
				
			||||||
                               &m,
 | 
					                               &m,
 | 
				
			||||||
                               true);
 | 
					                               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,11 +104,13 @@ 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->resource,
 | 
				
			||||||
                             data->res,
 | 
					                             data->res,
 | 
				
			||||||
                             "no permission");
 | 
					                             "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->resource,
 | 
				
			||||||
                             data->res,
 | 
					                             data->res,
 | 
				
			||||||
                             "error %d", data->res);
 | 
					                             "error %d", data->res);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue