From b7daa89f852e2144b5c4af788e985ac1655aa877 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 1 Jul 2022 17:08:17 -0300 Subject: [PATCH] linux-pipewire: Split initialization of core and streams This commit introduces an important distinction in the initialization process that is essential to future camera and audio work: it splits creating and connecting to the PipeWire socket, from connecting to specific PipeWire nodes. Right now, for the only consumer in existence - the ScreenCast portal code - this distinction is irrelevant, but from an API perspective it just makes sense to model it this way. --- plugins/linux-pipewire/pipewire.c | 47 ++++++++++++---------- plugins/linux-pipewire/pipewire.h | 7 ++-- plugins/linux-pipewire/screencast-portal.c | 9 ++++- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/plugins/linux-pipewire/pipewire.c b/plugins/linux-pipewire/pipewire.c index 8329a39da..922fa68e2 100644 --- a/plugins/linux-pipewire/pipewire.c +++ b/plugins/linux-pipewire/pipewire.c @@ -792,15 +792,9 @@ static const struct pw_core_events core_events = { /* obs_source_info methods */ -obs_pipewire_data *obs_pipewire_create(int pipewire_fd, int pipewire_node, - const char *stream_name, - struct pw_properties *stream_properties) +obs_pipewire_data *obs_pipewire_create(int pipewire_fd) { - struct spa_pod_builder pod_builder; - const struct spa_pod **params = NULL; obs_pipewire_data *obs_pw; - uint32_t n_params; - uint8_t params_buffer[2048]; obs_pw = bzalloc(sizeof(obs_pipewire_data)); obs_pw->pipewire_fd = pipewire_fd; @@ -833,17 +827,32 @@ obs_pipewire_data *obs_pipewire_create(int pipewire_fd, int pipewire_node, pw_core_add_listener(obs_pw->core, &obs_pw->core_listener, &core_events, obs_pw); + // Dispatch to receive the info core event + obs_pw->server_version_sync = pw_core_sync(obs_pw->core, PW_ID_CORE, + obs_pw->server_version_sync); + pw_thread_loop_wait(obs_pw->thread_loop); + pw_thread_loop_unlock(obs_pw->thread_loop); + + return obs_pw; +} + +void obs_pipewire_connect_stream(obs_pipewire_data *obs_pw, int pipewire_node, + const char *stream_name, + struct pw_properties *stream_properties) +{ + struct spa_pod_builder pod_builder; + const struct spa_pod **params = NULL; + uint32_t n_params; + uint8_t params_buffer[2048]; + + pw_thread_loop_lock(obs_pw->thread_loop); + /* Signal to renegotiate */ obs_pw->reneg = pw_loop_add_event(pw_thread_loop_get_loop(obs_pw->thread_loop), renegotiate_format, obs_pw); blog(LOG_DEBUG, "[pipewire] registered event %p", obs_pw->reneg); - // Dispatch to receive the info core event - obs_pw->server_version_sync = pw_core_sync(obs_pw->core, PW_ID_CORE, - obs_pw->server_version_sync); - pw_thread_loop_wait(obs_pw->thread_loop); - /* Stream */ obs_pw->stream = pw_stream_new(obs_pw->core, stream_name, stream_properties); @@ -859,22 +868,18 @@ obs_pipewire_data *obs_pipewire_create(int pipewire_fd, int pipewire_node, if (!build_format_params(obs_pw, &pod_builder, ¶ms, &n_params)) { pw_thread_loop_unlock(obs_pw->thread_loop); - teardown_pipewire(obs_pw); - bfree(obs_pw); - return NULL; + return; } - pw_stream_connect( - obs_pw->stream, PW_DIRECTION_INPUT, pipewire_node, - PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS, params, - n_params); + pw_stream_connect(obs_pw->stream, PW_DIRECTION_INPUT, pipewire_node, + PW_STREAM_FLAG_AUTOCONNECT | + PW_STREAM_FLAG_MAP_BUFFERS, + params, n_params); blog(LOG_INFO, "[pipewire] Playing stream %p", obs_pw->stream); pw_thread_loop_unlock(obs_pw->thread_loop); bfree(params); - - return obs_pw; } void obs_pipewire_destroy(obs_pipewire_data *obs_pw) diff --git a/plugins/linux-pipewire/pipewire.h b/plugins/linux-pipewire/pipewire.h index 88becc124..4df410d04 100644 --- a/plugins/linux-pipewire/pipewire.h +++ b/plugins/linux-pipewire/pipewire.h @@ -27,9 +27,10 @@ typedef struct _obs_pipewire_data obs_pipewire_data; -obs_pipewire_data *obs_pipewire_create(int pipewire_fd, int pipewire_node, - const char *stream_name, - struct pw_properties *stream_properties); +obs_pipewire_data *obs_pipewire_create(int pipewire_fd); +void obs_pipewire_connect_stream(obs_pipewire_data *obs_pw, int pipewire_node, + const char *stream_name, + struct pw_properties *stream_properties); void obs_pipewire_destroy(obs_pipewire_data *obs_pw); void obs_pipewire_show(obs_pipewire_data *obs_pw); diff --git a/plugins/linux-pipewire/screencast-portal.c b/plugins/linux-pipewire/screencast-portal.c index e59075015..543d281ec 100644 --- a/plugins/linux-pipewire/screencast-portal.c +++ b/plugins/linux-pipewire/screencast-portal.c @@ -245,8 +245,13 @@ static void on_pipewire_remote_opened_cb(GObject *source, GAsyncResult *res, return; } - capture->obs_pw = obs_pipewire_create( - pipewire_fd, capture->pipewire_node, "OBS Studio", + capture->obs_pw = obs_pipewire_create(pipewire_fd); + + if (!capture->obs_pw) + return; + + obs_pipewire_connect_stream( + capture->obs_pw, capture->pipewire_node, "OBS Studio", pw_properties_new(PW_KEY_MEDIA_TYPE, "Video", PW_KEY_MEDIA_CATEGORY, "Capture", PW_KEY_MEDIA_ROLE, "Screen", NULL));