[mutter] screen-cast-src: Notify about the stream being closed after dispatch
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] screen-cast-src: Notify about the stream being closed after dispatch
- Date: Fri, 22 May 2020 00:30:06 +0000 (UTC)
commit c8e12ead08fd8ee8593b033c1f1a624f94a47ed9
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Tue May 12 16:14:00 2020 +0200
screen-cast-src: Notify about the stream being closed after dispatch
We're iterating inside the PipeWire loop when detecting PipeWire errors,
and shouldn't destroy the PipeWire objects mid-iteration. Avoid this by
first disabling the stream src (effectively stopping the recording),
then notifying about it being closed in an idle callback. The
notification eventually makes the rest of the screen cast code clean up
the objects, including the src and the associated PipeWire objects, but
will do so outside the PipeWire loop iteration.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1251
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1251
src/backends/meta-screen-cast-stream-src.c | 31 ++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
---
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index 544ed27a3..e3a85c101 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -68,6 +68,7 @@ typedef struct _MetaPipeWireSource
{
GSource base;
+ MetaScreenCastStreamSrc *src;
struct pw_loop *pipewire_loop;
} MetaPipeWireSource;
@@ -81,6 +82,7 @@ typedef struct _MetaScreenCastStreamSrcPrivate
struct spa_hook pipewire_core_listener;
gboolean is_enabled;
+ gboolean emit_closed_after_dispatch;
struct pw_stream *pipewire_stream;
struct spa_hook pipewire_stream_listener;
@@ -540,12 +542,6 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
priv->is_enabled = FALSE;
}
-static void
-meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src)
-{
- g_signal_emit (src, signals[CLOSED], 0);
-}
-
static void
on_stream_state_changed (void *data,
enum pw_stream_state old,
@@ -560,7 +556,9 @@ on_stream_state_changed (void *data,
{
case PW_STREAM_STATE_ERROR:
g_warning ("pipewire stream error: %s", error_message);
- meta_screen_cast_stream_src_notify_closed (src);
+ if (meta_screen_cast_stream_src_is_enabled (src))
+ meta_screen_cast_stream_src_disable (src);
+ priv->emit_closed_after_dispatch = TRUE;
break;
case PW_STREAM_STATE_PAUSED:
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
@@ -828,11 +826,17 @@ on_core_error (void *data,
const char *message)
{
MetaScreenCastStreamSrc *src = data;
+ MetaScreenCastStreamSrcPrivate *priv =
+ meta_screen_cast_stream_src_get_instance_private (src);
g_warning ("pipewire remote error: id:%u %s", id, message);
if (id == PW_ID_CORE && res == -EPIPE)
- meta_screen_cast_stream_src_notify_closed (src);
+ {
+ if (meta_screen_cast_stream_src_is_enabled (src))
+ meta_screen_cast_stream_src_disable (src);
+ priv->emit_closed_after_dispatch = TRUE;
+ }
}
static gboolean
@@ -849,12 +853,18 @@ pipewire_loop_source_dispatch (GSource *source,
gpointer user_data)
{
MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source;
+ MetaScreenCastStreamSrc *src = pipewire_source->src;
+ MetaScreenCastStreamSrcPrivate *priv =
+ meta_screen_cast_stream_src_get_instance_private (src);
int result;
result = pw_loop_iterate (pipewire_source->pipewire_loop, 0);
if (result < 0)
g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
+ if (priv->emit_closed_after_dispatch)
+ g_signal_emit (src, signals[CLOSED], 0);
+
return TRUE;
}
@@ -876,13 +886,14 @@ static GSourceFuncs pipewire_source_funcs =
};
static MetaPipeWireSource *
-create_pipewire_source (void)
+create_pipewire_source (MetaScreenCastStreamSrc *src)
{
MetaPipeWireSource *pipewire_source;
pipewire_source =
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
sizeof (MetaPipeWireSource));
+ pipewire_source->src = src;
pipewire_source->pipewire_loop = pw_loop_new (NULL);
if (!pipewire_source->pipewire_loop)
{
@@ -914,7 +925,7 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
- priv->pipewire_source = create_pipewire_source ();
+ priv->pipewire_source = create_pipewire_source (src);
if (!priv->pipewire_source)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]