mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-14 06:59:57 -05:00
work on state changes
Make things work better after errors
This commit is contained in:
parent
baada0a330
commit
8804980c8f
7 changed files with 116 additions and 68 deletions
|
|
@ -75,6 +75,51 @@ pinos_link_update_state (PinosLink *link,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
complete_ready (void *obj,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosPort *port = data;
|
||||
if (SPA_RESULT_IS_OK (res)) {
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
pinos_log_debug ("port %p: state READY", port);
|
||||
}
|
||||
else
|
||||
pinos_log_warn ("port %p: failed to go to READY", port);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_paused (void *obj,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosPort *port = data;
|
||||
if (SPA_RESULT_IS_OK (res)) {
|
||||
port->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_log_debug ("port %p: state PAUSED", port);
|
||||
}
|
||||
else
|
||||
pinos_log_warn ("port %p: failed to go to PAUSED", port);
|
||||
}
|
||||
|
||||
static void
|
||||
complete_streaming (void *obj,
|
||||
void *data,
|
||||
SpaResult res,
|
||||
uint32_t id)
|
||||
{
|
||||
PinosPort *port = data;
|
||||
if (SPA_RESULT_IS_OK (res)) {
|
||||
port->state = SPA_PORT_STATE_STREAMING;
|
||||
pinos_log_debug ("port %p: state STREAMING", port);
|
||||
}
|
||||
else
|
||||
pinos_log_warn ("port %p: failed to go to STREAMING", port);
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
do_negotiate (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
||||
{
|
||||
|
|
@ -121,8 +166,7 @@ do_negotiate (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error set output format: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_READY;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, complete_ready, this->output);
|
||||
}
|
||||
if (in_state == SPA_PORT_STATE_CONFIGURE) {
|
||||
pinos_log_debug ("link %p: doing set format on input", this);
|
||||
|
|
@ -134,8 +178,7 @@ do_negotiate (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error set input format: %d", res2);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_READY;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res2, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->input->node, res2, complete_ready, this->input);
|
||||
res = res2 != SPA_RESULT_OK ? res2 : res;
|
||||
}
|
||||
return res;
|
||||
|
|
@ -507,8 +550,7 @@ do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error alloc output buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, complete_paused, this->output);
|
||||
this->output->buffers = impl->buffers;
|
||||
this->output->n_buffers = impl->n_buffers;
|
||||
this->output->allocated = true;
|
||||
|
|
@ -524,8 +566,7 @@ do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error alloc input buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, complete_paused, this->input);
|
||||
this->input->buffers = impl->buffers;
|
||||
this->input->n_buffers = impl->n_buffers;
|
||||
this->input->allocated = true;
|
||||
|
|
@ -545,8 +586,7 @@ do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error use input buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->input->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, complete_paused, this->input);
|
||||
this->input->buffers = impl->buffers;
|
||||
this->input->n_buffers = impl->n_buffers;
|
||||
this->input->allocated = false;
|
||||
|
|
@ -561,8 +601,7 @@ do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
asprintf (&error, "error use output buffers: %d", res);
|
||||
goto error;
|
||||
}
|
||||
this->output->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, complete_paused, this->output);
|
||||
this->output->buffers = impl->buffers;
|
||||
this->output->n_buffers = impl->n_buffers;
|
||||
this->output->allocated = false;
|
||||
|
|
@ -601,13 +640,11 @@ do_start (PinosLink *this, uint32_t in_state, uint32_t out_state)
|
|||
|
||||
if (in_state == SPA_PORT_STATE_PAUSED) {
|
||||
res = pinos_node_set_state (this->input->node, PINOS_NODE_STATE_RUNNING);
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
this->input->state = SPA_PORT_STATE_STREAMING;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, complete_streaming, this->input);
|
||||
}
|
||||
if (out_state == SPA_PORT_STATE_PAUSED) {
|
||||
res = pinos_node_set_state (this->output->node, PINOS_NODE_STATE_RUNNING);
|
||||
this->output->state = SPA_PORT_STATE_STREAMING;
|
||||
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
|
||||
pinos_work_queue_add (impl->work, this->output->node, res, complete_streaming, this->output);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
@ -621,7 +658,6 @@ check_states (PinosLink *this,
|
|||
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
|
||||
uint32_t in_state, out_state;
|
||||
|
||||
again:
|
||||
if (this->state == PINOS_LINK_STATE_ERROR)
|
||||
return SPA_RESULT_ERROR;
|
||||
|
||||
|
|
@ -646,14 +682,12 @@ again:
|
|||
if ((res = do_start (this, in_state, out_state)) != SPA_RESULT_OK)
|
||||
goto exit;
|
||||
|
||||
if (this->input->state != in_state)
|
||||
goto again;
|
||||
if (this->output->state != out_state)
|
||||
goto again;
|
||||
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
exit:
|
||||
if (SPA_RESULT_IS_ERROR (res)) {
|
||||
pinos_log_debug ("link %p: got error result %d", this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
pinos_work_queue_add (impl->work,
|
||||
this,
|
||||
SPA_RESULT_WAIT_SYNC,
|
||||
|
|
@ -906,15 +940,16 @@ clear_port_buffers (PinosLink *link, PinosPort *port)
|
|||
{
|
||||
PinosLinkImpl *impl = SPA_CONTAINER_OF (link, PinosLinkImpl, this);
|
||||
|
||||
if (impl->buffer_owner != port) {
|
||||
if (impl->buffer_owner != port && port->state > SPA_PORT_STATE_READY) {
|
||||
pinos_log_debug ("link %p: clear buffers on port %p", link, port);
|
||||
spa_node_port_use_buffers (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
pinos_log_debug ("port %p: state READY", port);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -937,7 +972,7 @@ do_link_remove_done (SpaLoop *loop,
|
|||
|
||||
if (this->input->node->n_used_input_links == 0 &&
|
||||
this->input->node->n_used_output_links == 0)
|
||||
pinos_node_set_state (this->input->node, PINOS_NODE_STATE_IDLE);
|
||||
pinos_node_update_state (this->input->node, PINOS_NODE_STATE_IDLE, NULL);
|
||||
|
||||
this->input = NULL;
|
||||
}
|
||||
|
|
@ -949,7 +984,7 @@ do_link_remove_done (SpaLoop *loop,
|
|||
|
||||
if (this->output->node->n_used_input_links == 0 &&
|
||||
this->output->node->n_used_output_links == 0)
|
||||
pinos_node_set_state (this->output->node, PINOS_NODE_STATE_IDLE);
|
||||
pinos_node_update_state (this->output->node, PINOS_NODE_STATE_IDLE, NULL);
|
||||
|
||||
this->output = NULL;
|
||||
}
|
||||
|
|
@ -971,10 +1006,12 @@ do_link_remove (SpaLoop *loop,
|
|||
PinosLink *this = user_data;
|
||||
|
||||
if (this->rt.input) {
|
||||
pinos_port_pause_rt (this->rt.input);
|
||||
spa_list_remove (&this->rt.input_link);
|
||||
this->rt.input = NULL;
|
||||
}
|
||||
if (this->rt.output) {
|
||||
pinos_port_pause_rt (this->rt.output);
|
||||
spa_list_remove (&this->rt.output_link);
|
||||
this->rt.output = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,9 @@ pause_node (PinosNode *this)
|
|||
{
|
||||
SpaResult res;
|
||||
|
||||
if (this->state <= PINOS_NODE_STATE_IDLE)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pinos_log_debug ("node %p: pause node", this);
|
||||
{
|
||||
SpaCommand cmd = SPA_COMMAND_INIT (this->core->type.command_node.Pause);
|
||||
|
|
@ -649,6 +652,7 @@ do_node_remove (SpaLoop *loop,
|
|||
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) {
|
||||
pinos_port_pause_rt (link->rt.input);
|
||||
spa_list_remove (&link->rt.input_link);
|
||||
link->rt.input = NULL;
|
||||
}
|
||||
|
|
@ -656,6 +660,7 @@ do_node_remove (SpaLoop *loop,
|
|||
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) {
|
||||
pinos_port_pause_rt (link->rt.output);
|
||||
spa_list_remove (&link->rt.output_link);
|
||||
link->rt.output = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,18 +199,22 @@ no_mem:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
pinos_port_pause (PinosPort *port)
|
||||
SpaResult
|
||||
pinos_port_pause_rt (PinosPort *port)
|
||||
{
|
||||
SpaCommand cmd = SPA_COMMAND_INIT (port->node->core->type.command_node.Pause);
|
||||
SpaResult res;
|
||||
|
||||
if (port->state <= SPA_PORT_STATE_PAUSED)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
port->state = SPA_PORT_STATE_PAUSED;
|
||||
return spa_node_port_send_command (port->node->node,
|
||||
res = spa_node_port_send_command (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
&cmd);
|
||||
port->state = SPA_PORT_STATE_PAUSED;
|
||||
pinos_log_debug ("port %p: state PAUSED", port);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SpaResult
|
||||
|
|
@ -240,15 +244,16 @@ do_remove_link_done (SpaLoop *loop,
|
|||
}
|
||||
}
|
||||
|
||||
if (!port->allocated) {
|
||||
if (!port->allocated && port->state > SPA_PORT_STATE_READY) {
|
||||
pinos_log_debug ("port %p: clear buffers on port", port);
|
||||
spa_node_port_use_buffers (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
pinos_log_debug ("port %p: state READY", port);
|
||||
}
|
||||
|
||||
if (node->n_used_output_links == 0 &&
|
||||
|
|
@ -273,9 +278,11 @@ do_remove_link (SpaLoop *loop,
|
|||
SpaResult res;
|
||||
|
||||
if (port->direction == PINOS_DIRECTION_INPUT) {
|
||||
pinos_port_pause_rt (link->rt.input);
|
||||
spa_list_remove (&link->rt.input_link);
|
||||
link->rt.input = NULL;
|
||||
} else {
|
||||
pinos_port_pause_rt (link->rt.output);
|
||||
spa_list_remove (&link->rt.output_link);
|
||||
link->rt.output = NULL;
|
||||
}
|
||||
|
|
@ -317,15 +324,18 @@ do_clear_buffers_done (SpaLoop *loop,
|
|||
PinosPort *port = user_data;
|
||||
SpaResult res;
|
||||
|
||||
pinos_log_debug ("port %p: clear buffers finish", port);
|
||||
if (port->state <= SPA_PORT_STATE_READY)
|
||||
return SPA_RESULT_OK;
|
||||
|
||||
pinos_log_debug ("port %p: clear buffers finish", port);
|
||||
res = spa_node_port_use_buffers (port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
NULL, 0);
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
port->buffers = NULL;
|
||||
port->n_buffers = 0;
|
||||
port->state = SPA_PORT_STATE_READY;
|
||||
pinos_log_debug ("port %p: state READY", port);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -342,7 +352,7 @@ do_clear_buffers (SpaLoop *loop,
|
|||
PinosNode *node = port->node;
|
||||
SpaResult res;
|
||||
|
||||
pinos_port_pause (port);
|
||||
pinos_port_pause_rt (port);
|
||||
|
||||
res = pinos_loop_invoke (node->core->main_loop->loop,
|
||||
do_clear_buffers_done,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ PinosLink * pinos_port_link (PinosPort *output
|
|||
SpaResult pinos_port_unlink (PinosPort *port,
|
||||
PinosLink *link);
|
||||
|
||||
SpaResult pinos_port_pause_rt (PinosPort *port);
|
||||
SpaResult pinos_port_clear_buffers (PinosPort *port);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ process_work_queue (SpaLoopUtils *utils,
|
|||
spa_list_remove (&item->link);
|
||||
|
||||
if (item->func) {
|
||||
pinos_log_debug ("work-queue %p: process work item %p %d", this, item->obj, item->seq);
|
||||
pinos_log_debug ("work-queue %p: process work item %p %d %d", this, item->obj, item->seq, item->res);
|
||||
item->func (item->obj, item->data, item->res, item->id);
|
||||
}
|
||||
spa_list_insert (impl->free_list.prev, &item->link);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue