mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Add link introspection
This commit is contained in:
		
							parent
							
								
									b969623ec8
								
							
						
					
					
						commit
						e6f45a7686
					
				
					 8 changed files with 156 additions and 39 deletions
				
			
		| 
						 | 
					@ -255,6 +255,46 @@ client_dispatch_func (void             *object,
 | 
				
			||||||
  return SPA_RESULT_OK;
 | 
					  return SPA_RESULT_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaResult
 | 
				
			||||||
 | 
					link_dispatch_func (void             *object,
 | 
				
			||||||
 | 
					                    PinosMessageType  type,
 | 
				
			||||||
 | 
					                    void             *message,
 | 
				
			||||||
 | 
					                    void             *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosContextImpl *impl = data;
 | 
				
			||||||
 | 
					  PinosContext *this = &impl->this;
 | 
				
			||||||
 | 
					  PinosProxy *proxy = object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (type) {
 | 
				
			||||||
 | 
					    case PINOS_MESSAGE_LINK_INFO:
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      PinosMessageLinkInfo *m = message;
 | 
				
			||||||
 | 
					      PinosSubscriptionEvent event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      pinos_log_debug ("got link info %d", type);
 | 
				
			||||||
 | 
					      if (proxy->user_data == NULL)
 | 
				
			||||||
 | 
					        event = PINOS_SUBSCRIPTION_EVENT_NEW;
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        event = PINOS_SUBSCRIPTION_EVENT_CHANGE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      proxy->user_data = pinos_link_info_update (proxy->user_data, m->info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (impl->subscribe_func) {
 | 
				
			||||||
 | 
					        impl->subscribe_func (this,
 | 
				
			||||||
 | 
					                              event,
 | 
				
			||||||
 | 
					                              proxy->type,
 | 
				
			||||||
 | 
					                              proxy->id,
 | 
				
			||||||
 | 
					                              impl->subscribe_data);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      pinos_log_warn ("unhandled message %d", type);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return SPA_RESULT_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SpaResult
 | 
					static SpaResult
 | 
				
			||||||
registry_dispatch_func (void             *object,
 | 
					registry_dispatch_func (void             *object,
 | 
				
			||||||
                        PinosMessageType  type,
 | 
					                        PinosMessageType  type,
 | 
				
			||||||
| 
						 | 
					@ -291,6 +331,11 @@ registry_dispatch_func (void             *object,
 | 
				
			||||||
        proxy->dispatch_func = client_dispatch_func;
 | 
					        proxy->dispatch_func = client_dispatch_func;
 | 
				
			||||||
        proxy->dispatch_data = impl;
 | 
					        proxy->dispatch_data = impl;
 | 
				
			||||||
      } else if (!strcmp (ng->type, PINOS_LINK_URI)) {
 | 
					      } else if (!strcmp (ng->type, PINOS_LINK_URI)) {
 | 
				
			||||||
 | 
					        proxy = pinos_proxy_new (this,
 | 
				
			||||||
 | 
					                                 SPA_ID_INVALID,
 | 
				
			||||||
 | 
					                                 this->uri.link);
 | 
				
			||||||
 | 
					        proxy->dispatch_func = link_dispatch_func;
 | 
				
			||||||
 | 
					        proxy->dispatch_data = impl;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (proxy) {
 | 
					      if (proxy) {
 | 
				
			||||||
        PinosMessageBind m;
 | 
					        PinosMessageBind m;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,3 +277,39 @@ pinos_client_info_free   (PinosClientInfo       *info)
 | 
				
			||||||
    pinos_spa_dict_destroy (info->props);
 | 
					    pinos_spa_dict_destroy (info->props);
 | 
				
			||||||
  free (info);
 | 
					  free (info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PinosLinkInfo *
 | 
				
			||||||
 | 
					pinos_link_info_update (PinosLinkInfo       *info,
 | 
				
			||||||
 | 
					                        const PinosLinkInfo *update)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint64_t change_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (update == NULL)
 | 
				
			||||||
 | 
					    return info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (info == NULL) {
 | 
				
			||||||
 | 
					    info = calloc (1, sizeof (PinosLinkInfo));
 | 
				
			||||||
 | 
					    change_mask = ~0;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    change_mask = info->change_mask | update->change_mask;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  info->id = update->id;
 | 
				
			||||||
 | 
					  info->change_mask = change_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (update->change_mask & (1 << 0))
 | 
				
			||||||
 | 
					    info->output_node_id = update->output_node_id;
 | 
				
			||||||
 | 
					  if (update->change_mask & (1 << 1))
 | 
				
			||||||
 | 
					    info->output_port_id = update->output_port_id;
 | 
				
			||||||
 | 
					  if (update->change_mask & (1 << 2))
 | 
				
			||||||
 | 
					    info->input_node_id = update->input_node_id;
 | 
				
			||||||
 | 
					  if (update->change_mask & (1 << 3))
 | 
				
			||||||
 | 
					    info->input_port_id = update->input_port_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return info;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					pinos_link_info_free (PinosLinkInfo       *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  free (info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -301,6 +301,10 @@ struct _PinosLinkInfo {
 | 
				
			||||||
  uint32_t input_port_id;
 | 
					  uint32_t input_port_id;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PinosLinkInfo *    pinos_link_info_update (PinosLinkInfo       *info,
 | 
				
			||||||
 | 
					                                           const PinosLinkInfo *update);
 | 
				
			||||||
 | 
					void               pinos_link_info_free   (PinosLinkInfo       *info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * PinosLinkInfoCallback:
 | 
					 * PinosLinkInfoCallback:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -606,37 +606,6 @@ stream_dispatch_func (void             *object,
 | 
				
			||||||
  PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
 | 
					  PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switch (type) {
 | 
					  switch (type) {
 | 
				
			||||||
    case PINOS_MESSAGE_SYNC:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_GET_REGISTRY:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_BIND:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_DESTROY:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_REMOVE_ID:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_CREATE_NODE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_CREATE_CLIENT_NODE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NODE_UPDATE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_PORT_UPDATE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_PORT_STATUS_CHANGE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NODE_STATE_CHANGE:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_CORE_INFO:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_MODULE_INFO:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NODE_INFO:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_CLIENT_INFO:
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_LINK_INFO:
 | 
					 | 
				
			||||||
      pinos_log_warn ("got unexpected message %d", type);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NOTIFY_DONE:
 | 
					 | 
				
			||||||
      pinos_log_warn ("notify done %d", type);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NOTIFY_GLOBAL:
 | 
					 | 
				
			||||||
      pinos_log_warn ("notify global %d", type);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE:
 | 
					 | 
				
			||||||
      pinos_log_warn ("notify global %d", type);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case PINOS_MESSAGE_CREATE_NODE_DONE:
 | 
					    case PINOS_MESSAGE_CREATE_NODE_DONE:
 | 
				
			||||||
      pinos_log_warn ("create node done %d", type);
 | 
					      pinos_log_warn ("create node done %d", type);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					@ -838,6 +807,7 @@ stream_dispatch_func (void             *object,
 | 
				
			||||||
      pinos_log_debug ("transport update %d %p", impl->rtfd, impl->trans);
 | 
					      pinos_log_debug ("transport update %d %p", impl->rtfd, impl->trans);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
    case PINOS_MESSAGE_INVALID:
 | 
					    case PINOS_MESSAGE_INVALID:
 | 
				
			||||||
      pinos_log_warn ("unhandled message %d", type);
 | 
					      pinos_log_warn ("unhandled message %d", type);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,17 +82,33 @@ typedef struct {
 | 
				
			||||||
} PinosProtocolNativeClient;
 | 
					} PinosProtocolNativeClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
client_destroy (PinosProtocolNativeClient *this)
 | 
					sync_destroy (void      *object,
 | 
				
			||||||
 | 
					              void      *data,
 | 
				
			||||||
 | 
					              SpaResult  res,
 | 
				
			||||||
 | 
					              uint32_t   id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  pinos_client_destroy (this->client);
 | 
					  PinosProtocolNativeClient *this = object;
 | 
				
			||||||
  spa_list_remove (&this->link);
 | 
					
 | 
				
			||||||
  pinos_loop_destroy_source (this->impl->core->main_loop->loop,
 | 
					 | 
				
			||||||
                             this->source);
 | 
					 | 
				
			||||||
  pinos_connection_destroy (this->connection);
 | 
					  pinos_connection_destroy (this->connection);
 | 
				
			||||||
  close (this->fd);
 | 
					  close (this->fd);
 | 
				
			||||||
  free (this);
 | 
					  free (this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					client_destroy (PinosProtocolNativeClient *this)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  pinos_loop_destroy_source (this->impl->core->main_loop->loop,
 | 
				
			||||||
 | 
					                             this->source);
 | 
				
			||||||
 | 
					  pinos_client_destroy (this->client);
 | 
				
			||||||
 | 
					  spa_list_remove (&this->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pinos_main_loop_defer (this->impl->core->main_loop,
 | 
				
			||||||
 | 
					                         this,
 | 
				
			||||||
 | 
					                         SPA_RESULT_WAIT_SYNC,
 | 
				
			||||||
 | 
					                         sync_destroy,
 | 
				
			||||||
 | 
					                         this);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SpaResult
 | 
					static SpaResult
 | 
				
			||||||
client_send_func (void             *object,
 | 
					client_send_func (void             *object,
 | 
				
			||||||
                  uint32_t          id,
 | 
					                  uint32_t          id,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,6 +277,8 @@ pinos_core_add_global (PinosCore           *core,
 | 
				
			||||||
                       PinosBindFunc        bind)
 | 
					                       PinosBindFunc        bind)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosGlobal *global;
 | 
					  PinosGlobal *global;
 | 
				
			||||||
 | 
					  PinosResource *registry;
 | 
				
			||||||
 | 
					  PinosMessageNotifyGlobal ng;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  global = calloc (1, sizeof (PinosGlobal));
 | 
					  global = calloc (1, sizeof (PinosGlobal));
 | 
				
			||||||
  global->core = core;
 | 
					  global->core = core;
 | 
				
			||||||
| 
						 | 
					@ -294,6 +296,14 @@ pinos_core_add_global (PinosCore           *core,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_log_debug ("global %p: new %u", global, global->id);
 | 
					  pinos_log_debug ("global %p: new %u", global, global->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ng.id = global->id;
 | 
				
			||||||
 | 
					  ng.type = spa_id_map_get_uri (core->uri.map, global->type);
 | 
				
			||||||
 | 
					  spa_list_for_each (registry, &core->registry_resource_list, link) {
 | 
				
			||||||
 | 
					    pinos_resource_send_message (registry,
 | 
				
			||||||
 | 
					                                 PINOS_MESSAGE_NOTIFY_GLOBAL,
 | 
				
			||||||
 | 
					                                 &ng,
 | 
				
			||||||
 | 
					                                 true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  return global;
 | 
					  return global;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -313,6 +323,8 @@ void
 | 
				
			||||||
pinos_global_destroy (PinosGlobal *global)
 | 
					pinos_global_destroy (PinosGlobal *global)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosCore *core = global->core;
 | 
					  PinosCore *core = global->core;
 | 
				
			||||||
 | 
					  PinosResource *registry;
 | 
				
			||||||
 | 
					  PinosMessageNotifyGlobalRemove ng;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_log_debug ("global %p: destroy", global);
 | 
					  pinos_log_debug ("global %p: destroy", global);
 | 
				
			||||||
  pinos_signal_emit (&global->destroy_signal, global);
 | 
					  pinos_signal_emit (&global->destroy_signal, global);
 | 
				
			||||||
| 
						 | 
					@ -322,6 +334,14 @@ pinos_global_destroy (PinosGlobal *global)
 | 
				
			||||||
  spa_list_remove (&global->link);
 | 
					  spa_list_remove (&global->link);
 | 
				
			||||||
  pinos_signal_emit (&core->global_removed, core, global);
 | 
					  pinos_signal_emit (&core->global_removed, core, global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ng.id = global->id;
 | 
				
			||||||
 | 
					  spa_list_for_each (registry, &core->registry_resource_list, link) {
 | 
				
			||||||
 | 
					    pinos_resource_send_message (registry,
 | 
				
			||||||
 | 
					                                 PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE,
 | 
				
			||||||
 | 
					                                 &ng,
 | 
				
			||||||
 | 
					                                 true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_main_loop_defer (core->main_loop,
 | 
					  pinos_main_loop_defer (core->main_loop,
 | 
				
			||||||
                         global,
 | 
					                         global,
 | 
				
			||||||
                         SPA_RESULT_WAIT_SYNC,
 | 
					                         SPA_RESULT_WAIT_SYNC,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -681,24 +681,48 @@ link_dispatch_func (void             *object,
 | 
				
			||||||
  return SPA_RESULT_OK;
 | 
					  return SPA_RESULT_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					link_unbind_func (void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosResource *resource = data;
 | 
				
			||||||
 | 
					  spa_list_remove (&resource->link);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
link_bind_func (PinosGlobal *global,
 | 
					link_bind_func (PinosGlobal *global,
 | 
				
			||||||
                PinosClient *client,
 | 
					                PinosClient *client,
 | 
				
			||||||
                uint32_t     version,
 | 
					                uint32_t     version,
 | 
				
			||||||
                uint32_t     id)
 | 
					                uint32_t     id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  PinosLink *this = global->object;
 | 
				
			||||||
  PinosResource *resource;
 | 
					  PinosResource *resource;
 | 
				
			||||||
 | 
					  PinosMessageLinkInfo m;
 | 
				
			||||||
 | 
					  PinosLinkInfo info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  resource = pinos_resource_new (client,
 | 
					  resource = pinos_resource_new (client,
 | 
				
			||||||
                                 id,
 | 
					                                 id,
 | 
				
			||||||
                                 global->core->uri.link,
 | 
					                                 global->core->uri.link,
 | 
				
			||||||
                                 global->object,
 | 
					                                 global->object,
 | 
				
			||||||
                                 NULL);
 | 
					                                 link_unbind_func);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  resource->dispatch_func = link_dispatch_func;
 | 
					  resource->dispatch_func = link_dispatch_func;
 | 
				
			||||||
  resource->dispatch_data = client;
 | 
					  resource->dispatch_data = global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_log_debug ("link %p: bound to %d", global->object, resource->id);
 | 
					  pinos_log_debug ("link %p: bound to %d", global->object, resource->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (this->resource_list.prev, &resource->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  m.info = &info;
 | 
				
			||||||
 | 
					  info.id = resource->id;
 | 
				
			||||||
 | 
					  info.change_mask = ~0;
 | 
				
			||||||
 | 
					  info.output_node_id = this->output ? this->output->node->global->id : -1;
 | 
				
			||||||
 | 
					  info.output_port_id = this->output ? this->output->port_id : -1;
 | 
				
			||||||
 | 
					  info.input_node_id = this->input ? this->input->node->global->id : -1;
 | 
				
			||||||
 | 
					  info.input_port_id = this->input ? this->input->port_id : -1;
 | 
				
			||||||
 | 
					  pinos_resource_send_message (resource,
 | 
				
			||||||
 | 
					                               PINOS_MESSAGE_LINK_INFO,
 | 
				
			||||||
 | 
					                               &m,
 | 
				
			||||||
 | 
					                               true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PinosLink *
 | 
					PinosLink *
 | 
				
			||||||
| 
						 | 
					@ -722,6 +746,7 @@ pinos_link_new (PinosCore       *core,
 | 
				
			||||||
  this->input = input;
 | 
					  this->input = input;
 | 
				
			||||||
  this->output = output;
 | 
					  this->output = output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_init (&this->resource_list);
 | 
				
			||||||
  pinos_signal_init (&this->destroy_signal);
 | 
					  pinos_signal_init (&this->destroy_signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  impl->format_filter = format_filter;
 | 
					  impl->format_filter = format_filter;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,9 +52,10 @@ struct _PinosLink {
 | 
				
			||||||
  PINOS_SIGNAL (destroy_signal, (PinosListener *,
 | 
					  PINOS_SIGNAL (destroy_signal, (PinosListener *,
 | 
				
			||||||
                                 PinosLink *));
 | 
					                                 PinosLink *));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SpaList resource_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosPort    *output;
 | 
					  PinosPort    *output;
 | 
				
			||||||
  SpaList       output_link;
 | 
					  SpaList       output_link;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  PinosPort    *input;
 | 
					  PinosPort    *input;
 | 
				
			||||||
  SpaList       input_link;
 | 
					  SpaList       input_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue