mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
gtk: Marshall state changes in the main thread
Gtk is not MT safe thus we need to make sure that everything is done in the main thread when working with it. https://bugzilla.gnome.org/show_bug.cgi?id=755251
This commit is contained in:
parent
afdea505a0
commit
c3f7272929
1 changed files with 90 additions and 7 deletions
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue