summaryrefslogtreecommitdiff
path: root/ext/gtk/gstgtkbasesink.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/gtk/gstgtkbasesink.c')
-rw-r--r--ext/gtk/gstgtkbasesink.c97
1 files changed, 90 insertions, 7 deletions
diff --git a/ext/gtk/gstgtkbasesink.c b/ext/gtk/gstgtkbasesink.c
index 6321bdaae..41bb7f23c 100644
--- a/ext/gtk/gstgtkbasesink.c
+++ b/ext/gtk/gstgtkbasesink.c
@@ -77,6 +77,54 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink,
GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_sink,
"gtkbasesink", 0, "Gtk Video Sink base class"));
+struct invoke_context
+{
+ GThreadFunc func;
+ gpointer data;
+ GMutex lock;
+ GCond cond;
+ gboolean fired;
+
+ gpointer res;
+};
+
+static gboolean
+_invoke_func (struct invoke_context *info)
+{
+ g_mutex_lock (&info->lock);
+ info->res = info->func (info->data);
+ info->fired = TRUE;
+ g_cond_signal (&info->cond);
+ g_mutex_unlock (&info->lock);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gpointer
+_invoke_on_main (GThreadFunc func, gpointer data)
+{
+ GMainContext *main_context = g_main_context_default ();
+ struct invoke_context info;
+
+ g_mutex_init (&info.lock);
+ g_cond_init (&info.cond);
+ info.fired = FALSE;
+ info.func = func;
+ info.data = data;
+
+ g_main_context_invoke (main_context, (GSourceFunc) _invoke_func, &info);
+
+ g_mutex_lock (&info.lock);
+ while (!info.fired)
+ g_cond_wait (&info.cond, &info.lock);
+ g_mutex_unlock (&info.lock);
+
+ g_mutex_clear (&info.lock);
+ g_cond_clear (&info.cond);
+
+ return info.res;
+}
+
static void
gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass)
{
@@ -207,8 +255,21 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
switch (prop_id) {
case PROP_WIDGET:
- g_value_set_object (value, gst_gtk_base_sink_get_widget (gtk_sink));
+ {
+ GObject *widget = NULL;
+
+ GST_OBJECT_LOCK (gtk_sink);
+ if (gtk_sink->widget != NULL)
+ widget = G_OBJECT (gtk_sink->widget);
+ GST_OBJECT_UNLOCK (gtk_sink);
+
+ if (!widget)
+ widget = _invoke_on_main ((GThreadFunc) gst_gtk_base_sink_get_widget,
+ gtk_sink);
+
+ g_value_set_object (value, widget);
break;
+ }
case PROP_FORCE_ASPECT_RATIO:
g_value_set_boolean (value, gtk_sink->force_aspect_ratio);
break;
@@ -273,7 +334,7 @@ gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface)
}
static gboolean
-gst_gtk_base_sink_start (GstBaseSink * bsink)
+gst_gtk_base_sink_start_on_main (GstBaseSink * bsink)
{
GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink);
GstGtkBaseSinkClass *klass = GST_GTK_BASE_SINK_GET_CLASS (bsink);
@@ -303,7 +364,14 @@ gst_gtk_base_sink_start (GstBaseSink * bsink)
}
static gboolean
-gst_gtk_base_sink_stop (GstBaseSink * bsink)
+gst_gtk_base_sink_start (GstBaseSink * bsink)
+{
+ return ! !_invoke_on_main ((GThreadFunc) gst_gtk_base_sink_start_on_main,
+ bsink);
+}
+
+static gboolean
+gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink)
{
GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink);
@@ -317,11 +385,17 @@ gst_gtk_base_sink_stop (GstBaseSink * bsink)
}
static gboolean
-_show_window_cb (GstGtkBaseSink * gtk_sink)
+gst_gtk_base_sink_stop (GstBaseSink * bsink)
{
- gtk_widget_show_all (gtk_sink->window);
+ return ! !_invoke_on_main ((GThreadFunc) gst_gtk_base_sink_stop_on_main,
+ bsink);
+}
- return FALSE;
+static void
+gst_gtk_widget_show_all_and_unref (GtkWidget * widget)
+{
+ gtk_widget_show_all (widget);
+ g_object_unref (widget);
}
static GstStateChangeReturn
@@ -340,11 +414,20 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition)
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
+ {
+ GtkWindow *window = NULL;
+
GST_OBJECT_LOCK (gtk_sink);
if (gtk_sink->window)
- g_idle_add ((GSourceFunc) _show_window_cb, gtk_sink);
+ window = g_object_ref (gtk_sink->window);
GST_OBJECT_UNLOCK (gtk_sink);
+
+ if (window)
+ _invoke_on_main ((GThreadFunc) gst_gtk_widget_show_all_and_unref,
+ window);
+
break;
+ }
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_OBJECT_LOCK (gtk_sink);
if (gtk_sink->widget)