summaryrefslogtreecommitdiff
path: root/ext/gtk/gtkgstwidget.c
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2015-07-15 14:32:42 -0400
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2015-07-16 17:05:36 -0400
commit0bc7e9a240dd55eb1b4bc34e730a8a6e28e2de53 (patch)
treeab70f3073307d240fbeac171777004e2bed33941 /ext/gtk/gtkgstwidget.c
parent53a431a3239918cd04763879845e09bc87bb8883 (diff)
downloadgstreamer-plugins-bad-0bc7e9a240dd55eb1b4bc34e730a8a6e28e2de53.tar.gz
gtk: Fix race between queue_draw and destroy
In GTK dispose can be called before the last ref is reached. This happens when you close the container window. The dispose will be explicitly called, and destroyed notify will be fired. This patch fixes this race by properly tracking the widget state. In the sink, we now set the widget pointer to NULL, so the widget will properly get created again if you set your pipeline to NULL state after the widget was destroy, and set it back to PLAYING. https://bugzilla.gnome.org/show_bug.cgi?id=751104
Diffstat (limited to 'ext/gtk/gtkgstwidget.c')
-rw-r--r--ext/gtk/gtkgstwidget.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/ext/gtk/gtkgstwidget.c b/ext/gtk/gtkgstwidget.c
index 3e2f9bb28..3fbb0ca4e 100644
--- a/ext/gtk/gtkgstwidget.c
+++ b/ext/gtk/gtkgstwidget.c
@@ -69,6 +69,10 @@ struct _GtkGstWidgetPrivate
GstBuffer *buffer;
GstCaps *caps;
GstVideoInfo v_info;
+
+ /* Pending queued idles callback */
+ guint draw_id;
+ guint resize_id;
};
static void
@@ -226,6 +230,12 @@ gtk_gst_widget_finalize (GObject * object)
gst_buffer_replace (&widget->priv->buffer, NULL);
g_mutex_clear (&widget->priv->lock);
+ if (widget->priv->draw_id)
+ g_source_remove (widget->priv->draw_id);
+
+ if (widget->priv->resize_id)
+ g_source_remove (widget->priv->resize_id);
+
G_OBJECT_CLASS (gtk_gst_widget_parent_class)->finalize (object);
}
@@ -331,6 +341,10 @@ gtk_gst_widget_new (void)
static gboolean
_queue_draw (GtkGstWidget * widget)
{
+ g_mutex_lock (&widget->priv->lock);
+ widget->priv->draw_id = 0;
+ g_mutex_unlock (&widget->priv->lock);
+
gtk_widget_queue_draw (GTK_WIDGET (widget));
return G_SOURCE_REMOVE;
@@ -339,8 +353,6 @@ _queue_draw (GtkGstWidget * widget)
void
gtk_gst_widget_set_buffer (GtkGstWidget * widget, GstBuffer * buffer)
{
- GMainContext *main_context = g_main_context_default ();
-
g_return_if_fail (GTK_IS_GST_WIDGET (widget));
g_return_if_fail (buffer == NULL || widget->priv->negotiated);
@@ -348,14 +360,21 @@ gtk_gst_widget_set_buffer (GtkGstWidget * widget, GstBuffer * buffer)
gst_buffer_replace (&widget->priv->buffer, buffer);
- g_mutex_unlock (&widget->priv->lock);
+ if (!widget->priv->draw_id) {
+ widget->priv->draw_id = g_idle_add_full (G_PRIORITY_DEFAULT,
+ (GSourceFunc) _queue_draw, widget, NULL);
+ }
- g_main_context_invoke (main_context, (GSourceFunc) _queue_draw, widget);
+ g_mutex_unlock (&widget->priv->lock);
}
static gboolean
_queue_resize (GtkGstWidget * widget)
{
+ g_mutex_lock (&widget->priv->lock);
+ widget->priv->resize_id = 0;
+ g_mutex_unlock (&widget->priv->lock);
+
gtk_widget_queue_resize (GTK_WIDGET (widget));
return G_SOURCE_REMOVE;
@@ -424,7 +443,6 @@ _calculate_par (GtkGstWidget * widget, GstVideoInfo * info)
gboolean
gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps)
{
- GMainContext *main_context = g_main_context_default ();
GstVideoInfo v_info;
g_return_val_if_fail (GTK_IS_GST_WIDGET (widget), FALSE);
@@ -455,15 +473,17 @@ gtk_gst_widget_set_caps (GtkGstWidget * widget, GstCaps * caps)
return FALSE;
}
+ gst_buffer_replace (&widget->priv->buffer, NULL);
gst_caps_replace (&widget->priv->caps, caps);
widget->priv->v_info = v_info;
widget->priv->negotiated = TRUE;
- g_mutex_unlock (&widget->priv->lock);
-
- gtk_widget_queue_resize (GTK_WIDGET (widget));
+ if (!widget->priv->resize_id) {
+ widget->priv->resize_id = g_idle_add_full (G_PRIORITY_DEFAULT,
+ (GSourceFunc) _queue_resize, widget, NULL);
+ }
- g_main_context_invoke (main_context, (GSourceFunc) _queue_resize, widget);
+ g_mutex_unlock (&widget->priv->lock);
return TRUE;
}