From 9bf04c7c4cb591fc78206db46fbf0996669a18b3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 7 Oct 2024 17:15:18 +0200 Subject: [PATCH] stream: improve the flush handling and docs Flush with drain calls the drained callback for each cycle until paused or resumed. Setting the stream to active again, clears the drained state and makes things resume. Flush without drain does not set the state to PAUSED but simply clears the queued data. This is mostly useful when pausing or stopping. At no point should the flush operation result in a PAUSED state change. --- src/pipewire/filter.c | 8 ++++++-- src/pipewire/filter.h | 5 ++++- src/pipewire/stream.c | 7 +++++-- src/pipewire/stream.h | 6 +++++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index 23fc9cc59..1a8d34dff 100644 --- a/src/pipewire/filter.c +++ b/src/pipewire/filter.c @@ -498,14 +498,18 @@ static int impl_send_command(void *object, const struct spa_command *command) { struct filter *impl = object; struct pw_filter *filter = &impl->this; + uint32_t id = SPA_NODE_COMMAND_ID(command); - switch (SPA_NODE_COMMAND_ID(command)) { + pw_log_debug("%p: command %s", impl, + spa_debug_type_find_name(spa_type_node_command_id, id)); + + switch (id) { case SPA_NODE_COMMAND_Suspend: case SPA_NODE_COMMAND_Flush: case SPA_NODE_COMMAND_Pause: pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl); - if (filter->state == PW_FILTER_STATE_STREAMING) { + if (filter->state == PW_FILTER_STATE_STREAMING && id != SPA_NODE_COMMAND_Flush) { pw_log_debug("%p: pause", filter); filter_set_state(filter, PW_FILTER_STATE_PAUSED, 0, NULL); } diff --git a/src/pipewire/filter.h b/src/pipewire/filter.h index 674ef4b7e..2f4b2267f 100644 --- a/src/pipewire/filter.h +++ b/src/pipewire/filter.h @@ -237,7 +237,10 @@ void *pw_filter_get_dsp_buffer(void *port_data, uint32_t n_samples); int pw_filter_set_active(struct pw_filter *filter, bool active); /** Flush a filter. When \a drain is true, the drained callback will - * be called when all data is played or recorded */ + * be called when all data is played or recorded. The filter can be resumed + * after the drain by setting it active again with + * \ref pw_filter_set_active(). A flush without a drain is mostly useful afer + * a state change to PAUSED, to flush any remaining data from the queues. */ int pw_filter_flush(struct pw_filter *filter, bool drain); /** Check if the filter is driving. The filter needs to have the diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 220b2ef9b..0abc41904 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -657,7 +657,7 @@ static int impl_send_command(void *object, const struct spa_command *command) case SPA_NODE_COMMAND_Pause: pw_loop_invoke(impl->main_loop, NULL, 0, NULL, 0, false, impl); - if (stream->state == PW_STREAM_STATE_STREAMING) { + if (stream->state == PW_STREAM_STATE_STREAMING && id != SPA_NODE_COMMAND_Flush) { pw_log_debug("%p: pause", stream); stream_set_state(stream, PW_STREAM_STATE_PAUSED, 0, NULL); } @@ -2314,8 +2314,11 @@ int pw_stream_set_active(struct pw_stream *stream, bool active) pw_impl_node_set_active(stream->node, active); - if (!active || impl->drained) + if (!active || impl->drained) { + if (impl->drained && impl->io != NULL) + impl->io->status = SPA_STATUS_NEED_DATA; impl->drained = impl->draining = false; + } return 0; } diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 0500330f1..60967daa3 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -556,7 +556,11 @@ int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer); int pw_stream_set_active(struct pw_stream *stream, bool active); /** Flush a stream. When \a drain is true, the drained callback will - * be called when all data is played or recorded */ + * be called when all data is played or recorded. The stream can be resumed + * after the drain by setting it active again with + * \ref pw_stream_set_active(). A flush without a drain is mostly useful afer + * a state change to PAUSED, to flush any remaining data from the queues and + * the converters. */ int pw_stream_flush(struct pw_stream *stream, bool drain); /** Check if the stream is driving. The stream needs to have the