mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
276 lines
7.5 KiB
C
276 lines
7.5 KiB
C
/* Pinos
|
|
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#include "config.h"
|
|
|
|
#include "pinos/server/core.h"
|
|
#include "pinos/server/module.h"
|
|
|
|
typedef struct {
|
|
PinosCore *core;
|
|
PinosProperties *properties;
|
|
|
|
PinosListener global_added;
|
|
PinosListener global_removed;
|
|
PinosListener port_added;
|
|
PinosListener port_removed;
|
|
PinosListener port_unlinked;
|
|
PinosListener link_state_changed;
|
|
} ModuleImpl;
|
|
|
|
static void
|
|
try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
|
|
{
|
|
PinosProperties *props;
|
|
const char *path;
|
|
char *error = NULL;
|
|
PinosLink *link;
|
|
|
|
props = node->properties;
|
|
if (props == NULL) {
|
|
pinos_log_debug ("module %p: node has no properties", impl);
|
|
return;
|
|
}
|
|
|
|
path = pinos_properties_get (props, "pinos.target.node");
|
|
|
|
pinos_log_debug ("module %p: try to find and link to node '%s'", impl, path);
|
|
|
|
if (path) {
|
|
PinosPort *target;
|
|
|
|
target = pinos_core_find_port (impl->core,
|
|
port,
|
|
atoi (path),
|
|
NULL,
|
|
NULL,
|
|
&error);
|
|
if (target == NULL)
|
|
goto error;
|
|
|
|
if (port->direction == PINOS_DIRECTION_OUTPUT)
|
|
link = pinos_port_link (port, target, NULL, NULL, &error);
|
|
else
|
|
link = pinos_port_link (target, port, NULL, NULL, &error);
|
|
|
|
if (link == NULL)
|
|
goto error;
|
|
|
|
pinos_link_activate (link);
|
|
}
|
|
return;
|
|
|
|
error:
|
|
{
|
|
pinos_node_update_state (node, PINOS_NODE_STATE_ERROR, error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
on_link_port_unlinked (PinosListener *listener,
|
|
PinosLink *link,
|
|
PinosPort *port)
|
|
{
|
|
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, port_unlinked);
|
|
|
|
pinos_log_debug ("module %p: link %p: port %p unlinked", impl, link, port);
|
|
if (port->direction == PINOS_DIRECTION_OUTPUT && link->input)
|
|
try_link_port (link->input->node, link->input, impl);
|
|
}
|
|
|
|
static void
|
|
on_link_state_changed (PinosListener *listener,
|
|
PinosLink *link)
|
|
{
|
|
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, link_state_changed);
|
|
PinosLinkState state;
|
|
|
|
state = link->state;
|
|
switch (state) {
|
|
case PINOS_LINK_STATE_ERROR:
|
|
{
|
|
PinosResource *resource;
|
|
|
|
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
|
|
|
|
spa_list_for_each (resource, &link->resource_list, link) {
|
|
pinos_resource_send_error (resource,
|
|
SPA_RESULT_ERROR,
|
|
link->error);
|
|
}
|
|
#if 0
|
|
if (link->input && link->input->node)
|
|
pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
|
|
if (link->output && link->output->node)
|
|
pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
case PINOS_LINK_STATE_UNLINKED:
|
|
pinos_log_debug ("module %p: link %p: unlinked", impl, link);
|
|
#if 0
|
|
if (link->input && link->input->node)
|
|
pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
|
|
if (link->output && link->output->node)
|
|
pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup ("node unlinked"));
|
|
#endif
|
|
break;
|
|
|
|
case PINOS_LINK_STATE_INIT:
|
|
case PINOS_LINK_STATE_NEGOTIATING:
|
|
case PINOS_LINK_STATE_ALLOCATING:
|
|
case PINOS_LINK_STATE_PAUSED:
|
|
case PINOS_LINK_STATE_RUNNING:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_port_added (PinosListener *listener,
|
|
PinosNode *node,
|
|
PinosPort *port)
|
|
{
|
|
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, port_added);
|
|
|
|
try_link_port (node, port, impl);
|
|
}
|
|
|
|
static void
|
|
on_port_removed (PinosListener *listener,
|
|
PinosNode *node,
|
|
PinosPort *port)
|
|
{
|
|
}
|
|
|
|
static void
|
|
on_node_created (PinosNode *node,
|
|
ModuleImpl *impl)
|
|
{
|
|
PinosPort *port;
|
|
|
|
spa_list_for_each (port, &node->input_ports, link)
|
|
on_port_added (&impl->port_added, node, port);
|
|
|
|
spa_list_for_each (port, &node->output_ports, link)
|
|
on_port_added (&impl->port_added, node, port);
|
|
}
|
|
|
|
static void
|
|
on_node_added (ModuleImpl *impl, PinosNode *node)
|
|
{
|
|
pinos_log_debug ("module %p: node %p added", impl, node);
|
|
|
|
if (node->state > PINOS_NODE_STATE_CREATING)
|
|
on_node_created (node, impl);
|
|
}
|
|
|
|
static void
|
|
on_node_removed (ModuleImpl *impl, PinosNode *node)
|
|
{
|
|
pinos_log_debug ("module %p: node %p removed", impl, node);
|
|
}
|
|
|
|
static void
|
|
on_global_added (PinosListener *listener,
|
|
PinosCore *core,
|
|
PinosGlobal *global)
|
|
{
|
|
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_added);
|
|
|
|
if (global->type == impl->core->uri.node) {
|
|
PinosNode *node = global->object;
|
|
on_node_added (impl, node);
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_global_removed (PinosListener *listener,
|
|
PinosCore *core,
|
|
PinosGlobal *global)
|
|
{
|
|
ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_removed);
|
|
|
|
if (global->type == impl->core->uri.node) {
|
|
PinosNode *node = global->object;
|
|
on_node_removed (impl, node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* module_new:
|
|
* @core: #PinosCore
|
|
* @properties: #PinosProperties
|
|
*
|
|
* Make a new #ModuleImpl object with given @properties
|
|
*
|
|
* Returns: a new #ModuleImpl
|
|
*/
|
|
static ModuleImpl *
|
|
module_new (PinosCore *core,
|
|
PinosProperties *properties)
|
|
{
|
|
ModuleImpl *impl;
|
|
|
|
impl = calloc (1, sizeof (ModuleImpl));
|
|
pinos_log_debug ("module %p: new", impl);
|
|
|
|
impl->core = core;
|
|
impl->properties = properties;
|
|
|
|
pinos_signal_add (&core->global_added, &impl->global_added, on_global_added);
|
|
pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
|
|
pinos_signal_add (&core->port_added, &impl->port_added, on_port_added);
|
|
pinos_signal_add (&core->port_removed, &impl->port_removed, on_port_removed);
|
|
pinos_signal_add (&core->port_unlinked, &impl->port_unlinked, on_link_port_unlinked);
|
|
pinos_signal_add (&core->link_state_changed, &impl->link_state_changed, on_link_state_changed);
|
|
|
|
return impl;
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
module_destroy (ModuleImpl *impl)
|
|
{
|
|
pinos_log_debug ("module %p: destroy", impl);
|
|
|
|
pinos_global_destroy (impl->global);
|
|
|
|
pinos_signal_remove (&impl->global_added);
|
|
pinos_signal_remove (&impl->global_removed);
|
|
pinos_signal_remove (&impl->port_added);
|
|
pinos_signal_remove (&impl->port_removed);
|
|
pinos_signal_remove (&impl->port_unlinked);
|
|
pinos_signal_remove (&impl->link_state_changed);
|
|
free (impl);
|
|
}
|
|
#endif
|
|
|
|
bool
|
|
pinos__module_init (PinosModule * module, const char * args)
|
|
{
|
|
module_new (module->core, NULL);
|
|
return true;
|
|
}
|