From 5f9effaa7eed143f1a65f3a335428cd128f8bc31 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Sun, 28 Mar 2021 17:45:41 -0400
Subject: [PATCH] audio: pipewire: Block while waiting on stream state info
Initializing streams, particularly capture streams, can take many milliseconds, which is a bit much for a busy wait. Use a blocking wait instead.
---
src/audio/pipewire/SDL_pipewire.c | 38 +++++++++++++++++++++++--------
src/audio/pipewire/SDL_pipewire.h | 5 ++--
2 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c
index 81e7946d0..811b0b210 100644
--- a/src/audio/pipewire/SDL_pipewire.c
+++ b/src/audio/pipewire/SDL_pipewire.c
@@ -983,8 +983,23 @@ input_callback(void *data)
PIPEWIRE_pw_stream_queue_buffer(stream, pw_buf);
}
-static const struct pw_stream_events stream_output_events = { PW_VERSION_STREAM_EVENTS, .process = output_callback };
-static const struct pw_stream_events stream_input_events = { PW_VERSION_STREAM_EVENTS, .process = input_callback };
+static void
+stream_state_changed_callback(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error)
+{
+ _THIS = data;
+
+ if (state == PW_STREAM_STATE_STREAMING || state == PW_STREAM_STATE_ERROR) {
+ SDL_AtomicSet(&this->hidden->stream_initialized, 1);
+ PIPEWIRE_pw_thread_loop_signal(this->hidden->loop, false);
+ }
+}
+
+static const struct pw_stream_events stream_output_events = { PW_VERSION_STREAM_EVENTS,
+ .state_changed = stream_state_changed_callback,
+ .process = output_callback };
+static const struct pw_stream_events stream_input_events = { PW_VERSION_STREAM_EVENTS,
+ .state_changed = stream_state_changed_callback,
+ .process = input_callback };
static int
PIPEWIRE_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
@@ -1005,7 +1020,7 @@ PIPEWIRE_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
const struct spa_pod * params = NULL;
struct SDL_PrivateAudioData *priv;
struct pw_properties * props;
- const char * app_name, *stream_name, *stream_role;
+ const char * app_name, *stream_name, *stream_role, *error;
const Uint32 node_id = this->handle == NULL ? PW_ID_ANY : PW_HANDLE_TO_ID(this->handle);
enum pw_stream_state state;
int res;
@@ -1120,14 +1135,17 @@ PIPEWIRE_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
/* Wait until the stream is either running or failed */
- do {
- const char *error;
- state = PIPEWIRE_pw_stream_get_state(priv->stream, &error);
+ PIPEWIRE_pw_thread_loop_lock(priv->loop);
+ if (!SDL_AtomicGet(&priv->stream_initialized)) {
+ PIPEWIRE_pw_thread_loop_wait(priv->loop);
+ }
+ PIPEWIRE_pw_thread_loop_unlock(priv->loop);
- if (state == PW_STREAM_STATE_ERROR) {
- return SDL_SetError("Pipewire: Stream error: %s", error);
- }
- } while (state != PW_STREAM_STATE_STREAMING);
+ state = PIPEWIRE_pw_stream_get_state(priv->stream, &error);
+
+ if (state == PW_STREAM_STATE_ERROR) {
+ return SDL_SetError("Pipewire: Stream error: %s", error);
+ }
return 0;
}
diff --git a/src/audio/pipewire/SDL_pipewire.h b/src/audio/pipewire/SDL_pipewire.h
index 567fd04a6..473e83158 100644
--- a/src/audio/pipewire/SDL_pipewire.h
+++ b/src/audio/pipewire/SDL_pipewire.h
@@ -37,8 +37,9 @@ struct SDL_PrivateAudioData
struct pw_context *context;
struct SDL_DataQueue *buffer;
- size_t buffer_period_size;
- Sint32 stride; /* Bytes-per-frame */
+ size_t buffer_period_size;
+ Sint32 stride; /* Bytes-per-frame */
+ SDL_atomic_t stream_initialized;
};
#endif /* SDL_pipewire_h_ */