diff --git a/src/pipewire/filter.c b/src/pipewire/filter.c index f21a161d5..7241cb344 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 15e318d09..65e6f4d21 100644 --- a/src/pipewire/filter.h +++ b/src/pipewire/filter.h @@ -238,7 +238,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 6e58d6df4..7e19d4beb 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -668,7 +668,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); } @@ -2325,8 +2325,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 f90917ccb..4f1206bf6 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -594,7 +594,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