From 9f7c481742f7f82037fd3b6f849b2a6b31713703 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 19 Sep 2024 19:03:38 +0200 Subject: [PATCH] stream: update state based on node Follow the state of the node and update the stream state accordingly. The most important part is that Start is async and so it's better to wait for completion from the node before emiting the STREAMING state. Don't wait for the completion of the Pause command of the node but send it to the stream immediately. Delaying it might make it come after the set_param calls are done and confuse the stream. --- src/pipewire/stream.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 93f63a5d0..220b2ef9b 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -648,7 +648,7 @@ static int impl_send_command(void *object, const struct spa_command *command) struct pw_stream *stream = &impl->this; uint32_t id = SPA_NODE_COMMAND_ID(command); - pw_log_info("%p: command %s", impl, + pw_log_debug("%p: command %s", impl, spa_debug_type_find_name(spa_type_node_command_id, id)); switch (id) { @@ -658,7 +658,6 @@ static int impl_send_command(void *object, const struct spa_command *command) pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl); if (stream->state == PW_STREAM_STATE_STREAMING) { - pw_log_debug("%p: pause", stream); stream_set_state(stream, PW_STREAM_STATE_PAUSED, 0, NULL); } @@ -666,13 +665,11 @@ static int impl_send_command(void *object, const struct spa_command *command) case SPA_NODE_COMMAND_Start: if (stream->state == PW_STREAM_STATE_PAUSED) { pw_log_debug("%p: start direction:%d", stream, impl->direction); - if (impl->direction == SPA_DIRECTION_INPUT) { if (impl->io != NULL) impl->io->status = SPA_STATUS_NEED_DATA; } copy_position(impl, impl->queued.incount); - stream_set_state(stream, PW_STREAM_STATE_STREAMING, 0, NULL); } break; default: @@ -1377,10 +1374,29 @@ static void node_event_info(void *data, const struct pw_node_info *info) } } +static void node_state_changed(void *data, enum pw_node_state old, + enum pw_node_state state, const char *error) +{ + struct pw_stream *stream = data; + + switch (state) { + case PW_NODE_STATE_RUNNING: + if (stream->state == PW_STREAM_STATE_PAUSED) + stream_set_state(stream, PW_STREAM_STATE_STREAMING, 0, NULL); + break; + case PW_NODE_STATE_ERROR: + stream_set_state(stream, PW_STREAM_STATE_ERROR, -EIO, error); + break; + default: + break; + } +} + static const struct pw_impl_node_events node_events = { PW_VERSION_IMPL_NODE_EVENTS, .destroy = node_event_destroy, .info_changed = node_event_info, + .state_changed = node_state_changed, }; static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)