From 370d19057259abb7e322ae328c0fc8042bc2cb63 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 1 Sep 2025 12:55:51 +0200 Subject: [PATCH] pulse: improve stream suspended state handling Only send out SUSPENDED event when there is a change in the suspended state. This avoids sending out unsuspend events when we simply uncork. Implement the fail_on_suspend flag for capture and playback streams. Instead of suspending those streams, we need to kill them. --- .../module-protocol-pulse/pulse-server.c | 20 +++++++++++++++---- src/modules/module-protocol-pulse/stream.c | 4 ++-- src/modules/module-protocol-pulse/stream.h | 2 ++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 5f5cd558f..944066852 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -1130,12 +1130,22 @@ static void stream_state_changed(void *data, enum pw_stream_state old, /* Don't emit suspended if we are creating a corked stream, as that will have a quick * RUNNING/SUSPENDED transition for initial negotiation */ if (stream->create_tag == SPA_ID_INVALID && !stream->corked) { - if (old == PW_STREAM_STATE_PAUSED && state == PW_STREAM_STATE_STREAMING) + if (old == PW_STREAM_STATE_PAUSED && state == PW_STREAM_STATE_STREAMING && + stream->is_suspended) { stream_send_suspended(stream, false); - if (old == PW_STREAM_STATE_STREAMING && state == PW_STREAM_STATE_PAUSED) - stream_send_suspended(stream, true); + stream->is_suspended = false; + } + if (old == PW_STREAM_STATE_STREAMING && state == PW_STREAM_STATE_PAUSED && + !stream->is_suspended) { + if (stream->fail_on_suspend) { + stream->killed = true; + destroy_stream = true; + } else { + stream_send_suspended(stream, true); + } + stream->is_suspended = true; + } } - if (destroy_stream) { pw_work_queue_add(impl->work_queue, stream, 0, do_destroy_stream, NULL); @@ -1742,6 +1752,7 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui stream->muted_set = muted_set; stream->is_underrun = true; stream->underrun_for = -1; + stream->fail_on_suspend = fail_on_suspend; pw_properties_set(props, "pulse.corked", corked ? "true" : "false"); @@ -2017,6 +2028,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint stream->volume_set = volume_set; stream->muted = muted; stream->muted_set = muted_set; + stream->fail_on_suspend = fail_on_suspend; if (client->quirks & QUIRK_REMOVE_CAPTURE_DONT_MOVE) no_move = false; diff --git a/src/modules/module-protocol-pulse/stream.c b/src/modules/module-protocol-pulse/stream.c index 7d0ac0cf4..7b7f6edc1 100644 --- a/src/modules/module-protocol-pulse/stream.c +++ b/src/modules/module-protocol-pulse/stream.c @@ -321,8 +321,8 @@ int stream_send_suspended(struct stream *stream, bool suspended) struct message *reply; uint32_t command; - pw_log_debug("client %p [%s]: stream %p SUSPENDED channel:%u", - client, client->name, stream, stream->channel); + pw_log_debug("client %p [%s]: stream %p SUSPENDED %d channel:%u", + client, client->name, stream, suspended, stream->channel); command = stream->direction == PW_DIRECTION_OUTPUT ? COMMAND_PLAYBACK_STREAM_SUSPENDED : diff --git a/src/modules/module-protocol-pulse/stream.h b/src/modules/module-protocol-pulse/stream.h index 3d017f391..7807fd491 100644 --- a/src/modules/module-protocol-pulse/stream.h +++ b/src/modules/module-protocol-pulse/stream.h @@ -98,6 +98,8 @@ struct stream { unsigned int pending:1; unsigned int is_idle:1; unsigned int is_paused:1; + unsigned int fail_on_suspend:1; + unsigned int is_suspended:1; }; struct stream *stream_new(struct client *client, enum stream_type type, uint32_t create_tag,