WIP object model change

Work on cleanup
This commit is contained in:
Wim Taymans 2016-11-15 13:29:58 +01:00
parent c25ccbb4ba
commit 0d21d633c9
26 changed files with 912 additions and 821 deletions

View file

@ -31,26 +31,6 @@
#include "pinos/dbus/org-pinos.h"
static PinosPort *
new_pinos_port (PinosNode *node, PinosDirection direction, uint32_t port)
{
PinosPort *np;
np = calloc (1, sizeof (PinosPort));
np->node = node;
np->direction = direction;
np->port = port;
np->links = g_ptr_array_new ();
pinos_signal_init (&np->destroy_signal);
return np;
}
static void
free_node_port (PinosPort *np)
{
g_ptr_array_free (np->links, TRUE);
g_slice_free (PinosPort, np);
}
typedef struct
{
PinosNode this;
@ -60,31 +40,21 @@ typedef struct
uint32_t seq;
gboolean async_init;
GList *input_ports;
GList *output_ports;
guint n_used_output_links;
guint n_used_input_links;
bool async_init;
GError *error;
guint idle_timeout;
struct {
GPtrArray *links;
} rt;
} PinosNodeImpl;
static void init_complete (PinosNode *this);
static void
update_port_ids (PinosNode *node, gboolean create)
update_port_ids (PinosNode *node, bool create)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
uint32_t *input_port_ids, *output_port_ids;
guint n_input_ports, n_output_ports, max_input_ports, max_output_ports;
guint i;
GList *ports;
unsigned int n_input_ports, n_output_ports, max_input_ports, max_output_ports;
unsigned int i;
SpaList *ports;
if (node->node == NULL)
return;
@ -104,80 +74,82 @@ update_port_ids (PinosNode *node, gboolean create)
max_output_ports,
output_port_ids);
node->input_port_map = realloc (node->input_port_map, sizeof (PinosPort *) * max_input_ports);
node->output_port_map = realloc (node->output_port_map, sizeof (PinosPort *) * max_output_ports);
pinos_log_debug ("node %p: update_port ids %u/%u, %u/%u", node,
n_input_ports, max_input_ports, n_output_ports, max_output_ports);
i = 0;
ports = impl->input_ports;
ports = &node->input_ports;
while (true) {
PinosPort *p = (ports ? ports->data : NULL);
PinosPort *p = (ports == &node->input_ports) ? NULL : SPA_CONTAINER_OF (ports, PinosPort, link);
if (p && i < n_input_ports && p->port == input_port_ids[i]) {
if (p && i < n_input_ports && p->port_id == input_port_ids[i]) {
node->input_port_map[p->port_id] = p;
pinos_log_debug ("node %p: exiting input port %d", node, input_port_ids[i]);
i++;
ports = g_list_next (ports);
} else if ((p && i < n_input_ports && input_port_ids[i] < p->port) || i < n_input_ports) {
ports = ports->next;
} else if ((p && i < n_input_ports && input_port_ids[i] < p->port_id) || i < n_input_ports) {
PinosPort *np;
pinos_log_debug ("node %p: input port added %d", node, input_port_ids[i]);
np = new_pinos_port (node, PINOS_DIRECTION_INPUT, input_port_ids[i]);
impl->input_ports = g_list_insert_before (impl->input_ports, ports, np);
np = pinos_port_new (node, PINOS_DIRECTION_INPUT, input_port_ids[i]);
spa_list_insert (ports, &np->link);
ports = np->link.next;
node->input_port_map[np->port_id] = np;
if (!impl->async_init)
pinos_signal_emit (&node->core->port_added, node, np);
i++;
} else if (p) {
GList *next;
pinos_log_debug ("node %p: input port removed %d", node, p->port);
next = g_list_next (ports);
impl->input_ports = g_list_delete_link (impl->input_ports, ports);
ports = next;
node->input_port_map[p->port_id] = NULL;
ports = ports->next;
if (!impl->async_init)
pinos_signal_emit (&node->core->port_removed, node, p);
free_node_port (p);
} else
pinos_log_debug ("node %p: input port removed %d", node, p->port_id);
pinos_port_destroy (p);
} else {
pinos_log_debug ("node %p: no more input ports", node);
break;
}
}
i = 0;
ports = impl->output_ports;
ports = &node->output_ports;
while (true) {
PinosPort *p = (ports ? ports->data : NULL);
PinosPort *p = (ports == &node->output_ports) ? NULL : SPA_CONTAINER_OF (ports, PinosPort, link);
if (p && i < n_output_ports && p->port == output_port_ids[i]) {
if (p && i < n_output_ports && p->port_id == output_port_ids[i]) {
pinos_log_debug ("node %p: exiting output port %d", node, output_port_ids[i]);
i++;
ports = g_list_next (ports);
} else if ((p && i < n_output_ports && output_port_ids[i] < p->port) || i < n_output_ports) {
ports = ports->next;
node->output_port_map[p->port_id] = p;
} else if ((p && i < n_output_ports && output_port_ids[i] < p->port_id) || i < n_output_ports) {
PinosPort *np;
pinos_log_debug ("node %p: output port added %d", node, output_port_ids[i]);
np = new_pinos_port (node, PINOS_DIRECTION_OUTPUT, output_port_ids[i]);
impl->output_ports = g_list_insert_before (impl->output_ports, ports, np);
np = pinos_port_new (node, PINOS_DIRECTION_OUTPUT, output_port_ids[i]);
spa_list_insert (ports, &np->link);
ports = np->link.next;
node->output_port_map[np->port_id] = np;
if (!impl->async_init)
pinos_signal_emit (&node->core->port_added, node, np);
i++;
} else if (p) {
GList *next;
pinos_log_debug ("node %p: output port removed %d", node, p->port);
next = g_list_next (ports);
impl->output_ports = g_list_delete_link (impl->output_ports, ports);
ports = next;
node->output_port_map[p->port_id] = NULL;
ports = ports->next;
if (!impl->async_init)
pinos_signal_emit (&node->core->port_removed, node, p);
free_node_port (p);
} else
pinos_log_debug ("node %p: output port removed %d", node, p->port_id);
pinos_port_destroy (p);
} else {
pinos_log_debug ("node %p: no more output ports", node);
break;
}
}
node->have_inputs = n_input_ports > 0;
node->have_outputs = n_output_ports > 0;
node->transport = pinos_transport_new (max_input_ports,
max_output_ports);
@ -227,31 +199,29 @@ start_node (PinosNode *this)
static SpaResult
suspend_node (PinosNode *this)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
SpaResult res = SPA_RESULT_OK;
GList *walk;
PinosPort *p;
pinos_log_debug ("node %p: suspend node", this);
for (walk = impl->input_ports; walk; walk = g_list_next (walk)) {
PinosPort *p = walk->data;
if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_INPUT, p->port, 0, NULL)) < 0)
pinos_log_warn ("error unset format output: %d", res);
spa_list_for_each (p, &this->input_ports, link) {
if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_INPUT, p->port_id, 0, NULL)) < 0)
pinos_log_warn ("error unset format input: %d", res);
p->buffers = NULL;
p->n_buffers = 0;
if (p->allocated)
pinos_memblock_free (&p->buffer_mem);
p->allocated = FALSE;
p->allocated = false;
}
for (walk = impl->output_ports; walk; walk = g_list_next (walk)) {
PinosPort *p = walk->data;
if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_OUTPUT, p->port, 0, NULL)) < 0)
spa_list_for_each (p, &this->output_ports, link) {
if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_OUTPUT, p->port_id, 0, NULL)) < 0)
pinos_log_warn ("error unset format output: %d", res);
p->buffers = NULL;
p->n_buffers = 0;
if (p->allocated)
pinos_memblock_free (&p->buffer_mem);
p->allocated = FALSE;
p->allocated = false;
}
return res;
}
@ -297,19 +267,19 @@ do_read_link (SpaPoll *poll,
size_t offset;
SpaResult res;
if (link->input == NULL)
if (link->rt.input == NULL)
return SPA_RESULT_OK;
while (link->in_ready > 0 && spa_ringbuffer_get_read_offset (&link->ringbuffer, &offset) > 0) {
SpaPortInput *input = &this->transport->inputs[link->input->port];
while (link->rt.in_ready > 0 && spa_ringbuffer_get_read_offset (&link->ringbuffer, &offset) > 0) {
SpaPortInput *input = &this->transport->inputs[link->rt.input->port_id];
input->buffer_id = link->queue[offset];
if ((res = spa_node_process_input (link->input->node->node)) < 0)
if ((res = spa_node_process_input (link->rt.input->node->node)) < 0)
pinos_log_warn ("node %p: error pushing buffer: %d, %d", this, res, input->status);
spa_ringbuffer_read_advance (&link->ringbuffer, 1);
link->in_ready--;
link->rt.in_ready--;
}
return SPA_RESULT_OK;
}
@ -319,7 +289,6 @@ static void
on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
{
PinosNode *this = user_data;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
switch (event->type) {
case SPA_NODE_EVENT_TYPE_INVALID:
@ -342,21 +311,20 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
case SPA_NODE_EVENT_TYPE_NEED_INPUT:
{
SpaNodeEventNeedInput *ni = (SpaNodeEventNeedInput *) event;
guint i;
PinosPort *port = this->input_port_map[ni->port_id];
PinosLink *link;
for (i = 0; i < impl->rt.links->len; i++) {
PinosLink *link = g_ptr_array_index (impl->rt.links, i);
if (link->input == NULL || link->input->port != ni->port_id)
spa_list_for_each (link, &port->rt.links, rt.input_link) {
if (link->rt.input == NULL || link->rt.output == NULL)
continue;
link->in_ready++;
spa_poll_invoke (&link->input->node->data_loop->poll,
link->rt.in_ready++;
spa_poll_invoke (&link->rt.input->node->data_loop->poll,
do_read_link,
SPA_ID_INVALID,
sizeof (PinosLink *),
&link,
link->input->node);
link->rt.input->node);
}
break;
}
@ -364,36 +332,33 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
{
SpaNodeEventHaveOutput *ho = (SpaNodeEventHaveOutput *) event;
SpaResult res;
guint i;
gboolean pushed = FALSE;
bool pushed = false;
SpaPortOutput *po = &this->transport->outputs[ho->port_id];
PinosPort *port = this->output_port_map[ho->port_id];
PinosLink *link;
if ((res = spa_node_process_output (node)) < 0) {
pinos_log_warn ("node %p: got pull error %d, %d", this, res, po->status);
break;
}
for (i = 0; i < impl->rt.links->len; i++) {
PinosLink *link = g_ptr_array_index (impl->rt.links, i);
PinosPort *output = link->output;
PinosPort *input = link->input;
spa_list_for_each (link, &port->rt.links, rt.output_link) {
size_t offset;
if (output == NULL || input == NULL ||
output->node->node != node || output->port != ho->port_id)
if (link->rt.input == NULL || link->rt.output == NULL)
continue;
if (spa_ringbuffer_get_write_offset (&link->ringbuffer, &offset) > 0) {
link->queue[offset] = po->buffer_id;
spa_ringbuffer_write_advance (&link->ringbuffer, 1);
spa_poll_invoke (&link->input->node->data_loop->poll,
spa_poll_invoke (&link->rt.input->node->data_loop->poll,
do_read_link,
SPA_ID_INVALID,
sizeof (PinosLink *),
&link,
link->input->node);
pushed = TRUE;
link->rt.input->node);
pushed = true;
}
}
if (!pushed) {
@ -406,16 +371,15 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
{
SpaResult res;
SpaNodeEventReuseBuffer *rb = (SpaNodeEventReuseBuffer *) event;
guint i;
PinosPort *port = this->input_port_map[rb->port_id];
PinosLink *link;
for (i = 0; i < impl->rt.links->len; i++) {
PinosLink *link = g_ptr_array_index (impl->rt.links, i);
if (link->input == NULL || link->input->port != rb->port_id || link->output == NULL)
spa_list_for_each (link, &port->rt.links, rt.input_link) {
if (link->rt.input == NULL || link->rt.output == NULL)
continue;
if ((res = spa_node_port_reuse_buffer (link->output->node->node,
link->output->port,
if ((res = spa_node_port_reuse_buffer (link->rt.output->node->node,
link->rt.output->port_id,
rb->buffer_id)) < 0)
pinos_log_warn ("node %p: error reuse buffer: %d", node, res);
}
@ -427,7 +391,7 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
}
}
static gboolean
static bool
handle_remove (PinosNode1 *interface,
GDBusMethodInvocation *invocation,
gpointer user_data)
@ -439,7 +403,7 @@ handle_remove (PinosNode1 *interface,
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("()"));
return TRUE;
return true;
}
static void
@ -503,14 +467,13 @@ pinos_node_new (PinosCore *core,
impl->iface = pinos_node1_skeleton_new ();
g_signal_connect (impl->iface, "handle-remove",
(GCallback) handle_remove,
node);
this);
this->state = PINOS_NODE_STATE_CREATING;
pinos_node1_set_state (impl->iface, this->state);
impl->rt.links = g_ptr_array_new_full (256, NULL);
//g_signal_connect (this, "notify", (GCallback) on_property_notify, this);
spa_list_init (&this->input_ports);
spa_list_init (&this->output_ports);
if (this->node->info) {
unsigned int i;
@ -527,12 +490,11 @@ pinos_node_new (PinosCore *core,
if (this->node->state > SPA_NODE_STATE_INIT) {
init_complete (this);
} else {
impl->async_init = TRUE;
impl->async_init = true;
pinos_main_loop_defer (this->core->main_loop,
this,
SPA_RESULT_RETURN_ASYNC (0),
(PinosDeferFunc) init_complete,
NULL,
NULL);
}
spa_list_insert (core->node_list.prev, &this->list);
@ -547,6 +509,75 @@ pinos_node_new (PinosCore *core,
return this;
}
static SpaResult
do_node_remove_done (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosNode *this = user_data;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosPort *port, *tmp;
pinos_main_loop_defer_cancel (this->core->main_loop, this, 0);
spa_list_for_each_safe (port, tmp, &this->input_ports, link)
pinos_port_destroy (port);
spa_list_for_each_safe (port, tmp, &this->output_ports, link)
pinos_port_destroy (port);
g_clear_object (&impl->iface);
free (this->name);
free (this->error);
if (this->properties)
pinos_properties_free (this->properties);
free (impl);
return SPA_RESULT_OK;
}
static SpaResult
do_node_remove (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosNode *this = user_data;
PinosPort *port, *tmp;
SpaResult res;
pause_node (this);
spa_list_for_each_safe (port, tmp, &this->input_ports, link) {
PinosLink *link, *tlink;
spa_list_for_each_safe (link, tlink, &port->rt.links, rt.input_link) {
spa_list_remove (&link->rt.input_link);
link->rt.input = NULL;
}
}
spa_list_for_each_safe (port, tmp, &this->output_ports, link) {
PinosLink *link, *tlink;
spa_list_for_each_safe (link, tlink, &port->rt.links, rt.output_link) {
spa_list_remove (&link->rt.output_link);
link->rt.output = NULL;
}
}
res = spa_poll_invoke (this->core->main_loop->poll,
do_node_remove_done,
seq,
0,
NULL,
this);
return res;
}
/**
* pinos_node_destroy:
* @node: a #PinosNode
@ -562,19 +593,15 @@ pinos_node_destroy (PinosNode * this)
pinos_log_debug ("node %p: destroy", impl);
pinos_signal_emit (&this->destroy_signal, this);
pinos_node_set_state (this, PINOS_NODE_STATE_SUSPENDED);
spa_list_remove (&this->list);
pinos_core_remove_global (this->core, this->global);
pinos_main_loop_defer_cancel (this->core->main_loop, this, 0);
g_clear_object (&impl->iface);
free (this->name);
g_clear_error (&impl->error);
if (this->properties)
pinos_properties_free (this->properties);
free (impl);
spa_poll_invoke (&this->data_loop->poll,
do_node_remove,
impl->seq++,
0,
NULL,
this);
}
/**
@ -605,37 +632,35 @@ PinosPort *
pinos_node_get_free_port (PinosNode *node,
PinosDirection direction)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
guint free_port, n_ports, max_ports;
GList *ports, *walk;
PinosPort *port = NULL;
unsigned int free_port, n_ports, max_ports;
SpaList *ports;
PinosPort *port = NULL, *p;
g_return_val_if_fail (node, NULL);
if (direction == PINOS_DIRECTION_INPUT) {
max_ports = node->transport->area->max_inputs;
n_ports = node->transport->area->n_inputs;
ports = impl->input_ports;
ports = &node->input_ports;
} else {
max_ports = node->transport->area->max_outputs;
n_ports = node->transport->area->n_outputs;
ports = impl->output_ports;
ports = &node->output_ports;
}
free_port = 0;
pinos_log_debug ("node %p: direction %d max %u, n %u, free_port %u", node, direction, max_ports, n_ports, free_port);
for (walk = ports; walk; walk = g_list_next (walk)) {
PinosPort *p = walk->data;
if (free_port < p->port) {
spa_list_for_each (p, ports, link) {
if (free_port < p->port_id) {
port = p;
break;
}
free_port = p->port + 1;
free_port = p->port_id + 1;
}
if (free_port >= max_ports && ports) {
port = ports->data;
if (free_port >= max_ports && !spa_list_is_empty (ports)) {
port = spa_list_first (ports, PinosPort, link);
} else
return NULL;
@ -643,343 +668,6 @@ pinos_node_get_free_port (PinosNode *node,
}
static SpaResult
do_add_link (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosNode *this = user_data;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosLink *link = ((PinosLink**)data)[0];
g_ptr_array_add (impl->rt.links, link);
return SPA_RESULT_OK;
}
static PinosLink *
find_link (PinosPort *output_port, PinosPort *input_port)
{
guint i;
for (i = 0; i < output_port->links->len; i++) {
PinosLink *pl = g_ptr_array_index (output_port->links, i);
if (pl->input == input_port) {
return pl;
}
}
return NULL;
}
PinosLink *
pinos_port_get_link (PinosPort *output_port,
PinosPort *input_port)
{
g_return_val_if_fail (output_port != NULL, NULL);
g_return_val_if_fail (input_port != NULL, NULL);
return find_link (output_port, input_port);
}
/**
* pinos_port_link:
* @output_port: an output port
* @input_port: an input port
* @format_filter: a format filter
* @properties: extra properties
* @error: an error or %NULL
*
* Make a link between @output_port and @input_port
*
* If the ports were already linked, the existing links will be returned.
*
* Returns: a new #PinosLink or %NULL and @error is set.
*/
PinosLink *
pinos_port_link (PinosPort *output_port,
PinosPort *input_port,
GPtrArray *format_filter,
PinosProperties *properties,
GError **error)
{
PinosNodeImpl *input_impl, *output_impl;
PinosNode *input_node, *output_node;
PinosLink *link;
g_return_val_if_fail (output_port != NULL, NULL);
g_return_val_if_fail (input_port != NULL, NULL);
output_node = output_port->node;
output_impl = SPA_CONTAINER_OF (output_node, PinosNodeImpl, this);
input_node = input_port->node;
input_impl = SPA_CONTAINER_OF (input_node, PinosNodeImpl, this);
pinos_log_debug ("port link %p:%u -> %p:%u", output_node, output_port->port, input_node, input_port->port);
if (output_node == input_node)
goto same_node;
if (input_port->links->len > 0)
goto was_linked;
link = find_link (output_port, input_port);
if (link == NULL) {
input_node->live = output_node->live;
if (output_node->clock)
input_node->clock = output_node->clock;
pinos_log_debug ("node %p: clock %p, live %d", output_node, output_node->clock, output_node->live);
link = pinos_link_new (output_node->core,
output_port,
input_port,
format_filter,
properties);
g_ptr_array_add (output_port->links, link);
g_ptr_array_add (input_port->links, link);
output_impl->n_used_output_links++;
input_impl->n_used_input_links++;
spa_poll_invoke (&output_node->data_loop->poll,
do_add_link,
SPA_ID_INVALID,
sizeof (PinosLink *),
&link,
output_node);
spa_poll_invoke (&input_node->data_loop->poll,
do_add_link,
SPA_ID_INVALID,
sizeof (PinosLink *),
&link,
input_node);
}
return link;
same_node:
{
g_set_error (error,
PINOS_ERROR,
PINOS_ERROR_NODE_LINK,
"can't link a node to itself");
return NULL;
}
was_linked:
{
g_set_error (error,
PINOS_ERROR,
PINOS_ERROR_NODE_LINK,
"input port was already linked");
return NULL;
}
}
static SpaResult
pinos_port_pause (PinosPort *port)
{
SpaNodeCommand cmd;
cmd.type = SPA_NODE_COMMAND_PAUSE;
cmd.size = sizeof (cmd);
return spa_node_port_send_command (port->node->node,
port->direction,
port->port,
&cmd);
}
static SpaResult
do_remove_link_done (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosPort *port = user_data;
PinosNode *this = port->node;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosLink *link = ((PinosLink**)data)[0];
pinos_log_debug ("port %p: finish unlink", port);
if (port->direction == PINOS_DIRECTION_OUTPUT) {
if (g_ptr_array_remove_fast (port->links, link))
impl->n_used_output_links--;
link->output = NULL;
} else {
if (g_ptr_array_remove_fast (port->links, link))
impl->n_used_input_links--;
link->input = NULL;
}
if (impl->n_used_output_links == 0 &&
impl->n_used_input_links == 0) {
pinos_node_report_idle (this);
}
if (!port->allocated) {
pinos_log_debug ("port %p: clear buffers on port", port);
spa_node_port_use_buffers (port->node->node,
port->direction,
port->port,
NULL, 0);
port->buffers = NULL;
port->n_buffers = 0;
}
pinos_main_loop_defer_complete (this->core->main_loop,
port,
seq,
SPA_RESULT_OK);
g_object_unref (link);
g_object_unref (port->node);
return SPA_RESULT_OK;
}
static SpaResult
do_remove_link (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosPort *port = user_data;
PinosNode *this = port->node;
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
PinosLink *link = ((PinosLink**)data)[0];
SpaResult res;
#if 0
/* FIXME we should only pause when all links are gone */
pinos_port_pause (port);
#endif
g_ptr_array_remove_fast (impl->rt.links, link);
res = spa_poll_invoke (this->core->main_loop->poll,
do_remove_link_done,
seq,
sizeof (PinosLink *),
&link,
port);
return res;
}
SpaResult
pinos_port_unlink (PinosPort *port, PinosLink *link)
{
SpaResult res;
PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, this);
pinos_log_debug ("port %p: start unlink %p", port, link);
g_object_ref (link);
g_object_ref (port->node);
res = spa_poll_invoke (&port->node->data_loop->poll,
do_remove_link,
impl->seq++,
sizeof (PinosLink *),
&link,
port);
return res;
}
static SpaResult
do_clear_buffers_done (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosPort *port = user_data;
PinosNode *this = port->node;
SpaResult res;
pinos_log_debug ("port %p: clear buffers finish", port);
res = spa_node_port_use_buffers (port->node->node,
port->direction,
port->port,
NULL, 0);
port->buffers = NULL;
port->n_buffers = 0;
pinos_main_loop_defer_complete (this->core->main_loop,
port,
seq,
res);
return res;
}
static SpaResult
do_clear_buffers (SpaPoll *poll,
bool async,
uint32_t seq,
size_t size,
void *data,
void *user_data)
{
PinosPort *port = user_data;
PinosNode *this = port->node;
SpaResult res;
pinos_port_pause (port);
res = spa_poll_invoke (this->core->main_loop->poll,
do_clear_buffers_done,
seq,
0, NULL,
port);
return res;
}
SpaResult
pinos_port_clear_buffers (PinosPort *port)
{
SpaResult res;
PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, this);
pinos_log_debug ("port %p: clear buffers", port);
res = spa_poll_invoke (&port->node->data_loop->poll,
do_clear_buffers,
impl->seq++,
0, NULL,
port);
return res;
}
/**
* pinos_node_get_ports:
* @node: a #PinosNode
* @direction: a #PinosDirection
*
* Get the port in @node.
*
* Returns: a #GList of #PinosPort g_list_free after usage.
*/
GList *
pinos_node_get_ports (PinosNode *node, PinosDirection direction)
{
GList *ports;
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
g_return_val_if_fail (node, NULL);
if (direction == PINOS_DIRECTION_INPUT) {
ports = impl->input_ports;
} else {
ports = impl->output_ports;
}
return ports;
}
static void
remove_idle_timeout (PinosNode *node)
{
@ -998,12 +686,10 @@ on_state_complete (PinosNode *node,
{
PinosNodeState state = GPOINTER_TO_INT (data);
pinos_log_debug ("node %p: state complete %d", node, res);
if (SPA_RESULT_IS_ERROR (res)) {
GError *error = NULL;
g_set_error (&error,
PINOS_ERROR,
PINOS_ERROR_NODE_STATE,
"error changing node state: %d", res);
char *error;
asprintf (&error, "error changing node state: %d", res);
pinos_node_report_error (node, error);
} else
pinos_node_update_state (node, state);
@ -1060,8 +746,7 @@ pinos_node_set_state (PinosNode *node,
node,
res,
(PinosDeferFunc) on_state_complete,
GINT_TO_POINTER (state),
NULL);
GINT_TO_POINTER (state));
return res;
}
@ -1098,30 +783,30 @@ pinos_node_update_state (PinosNode *node,
/**
* pinos_node_report_error:
* @node: a #PinosNode
* @error: a #GError
* @error: an error message
*
* Report an error from within @node.
*/
void
pinos_node_report_error (PinosNode *node,
GError *error)
char *error)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
PinosNodeState old;
g_return_if_fail (node);
g_clear_error (&impl->error);
free (node->error);
remove_idle_timeout (node);
impl->error = error;
node->error = error;
old = node->state;
node->state = PINOS_NODE_STATE_ERROR;
pinos_log_debug ("node %p: got error state %s", node, error->message);
pinos_log_debug ("node %p: got error state %s", node, error);
pinos_node1_set_state (impl->iface, PINOS_NODE_STATE_ERROR);
pinos_signal_emit (&node->core->node_state_changed, node, old, node->state);
}
static gboolean
static bool
idle_timeout (PinosNode *node)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);