clapper-gtk: video: Support finding widget within bin elements

When a video sink is set to some bin, also check sinks within it
in search for a widget that can be used as video main child
This commit is contained in:
Rafał Dzięgiel
2024-04-19 16:39:02 +02:00
parent 2aecd65735
commit 36c166813e

View File

@@ -969,46 +969,78 @@ _player_state_changed_cb (ClapperPlayer *player,
_set_buffering_animation_enabled (self, state == CLAPPER_PLAYER_STATE_BUFFERING); _set_buffering_animation_enabled (self, state == CLAPPER_PLAYER_STATE_BUFFERING);
} }
static GtkWidget *
_get_widget_from_video_sink (GstElement *vsink)
{
GtkWidget *widget = NULL;
GParamSpec *pspec;
if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (vsink), "widget"))
&& pspec->value_type == GTK_TYPE_WIDGET) {
GST_DEBUG ("Video sink provides a widget");
g_object_get (vsink, "widget", &widget, NULL);
} else if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (vsink), "paintable"))
&& pspec->value_type == GDK_TYPE_PAINTABLE) {
GdkPaintable *paintable = NULL;
GST_DEBUG ("Video sink provides a paintable");
g_object_get (vsink, "paintable", &paintable, NULL);
widget = g_object_ref_sink (gtk_picture_new ());
gtk_picture_set_paintable (GTK_PICTURE (widget), paintable);
g_object_unref (paintable);
}
return widget;
}
static void static void
_video_sink_changed_cb (ClapperPlayer *player, _video_sink_changed_cb (ClapperPlayer *player,
GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkVideo *self) GParamSpec *pspec G_GNUC_UNUSED, ClapperGtkVideo *self)
{ {
GstElement *vsink = clapper_player_get_video_sink (player); GstElement *vsink = clapper_player_get_video_sink (player);
GtkWidget *child = NULL; GtkWidget *widget = NULL;
GST_DEBUG_OBJECT (self, "Video sink changed to: %" GST_PTR_FORMAT, vsink); GST_DEBUG_OBJECT (self, "Video sink changed to: %" GST_PTR_FORMAT, vsink);
if (vsink) { if (vsink) {
GParamSpec *pspec; widget = _get_widget_from_video_sink (vsink);
if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (vsink), "widget")) if (!widget && GST_IS_BIN (vsink)) {
&& pspec->value_type == GTK_TYPE_WIDGET) { GstIterator *iter;
g_object_get (vsink, "widget", &child, NULL); GValue value = G_VALUE_INIT;
GST_DEBUG_OBJECT (self, "Video sink provides a widget");
} else if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (vsink), "paintable"))
&& pspec->value_type == GDK_TYPE_PAINTABLE) {
GdkPaintable *paintable = NULL;
g_object_get (vsink, "paintable", &paintable, NULL); iter = gst_bin_iterate_recurse (GST_BIN_CAST (vsink));
GST_DEBUG_OBJECT (self, "Video sink provides a paintable");
child = gtk_picture_new (); while (gst_iterator_next (iter, &value) == GST_ITERATOR_OK) {
gtk_picture_set_paintable (GTK_PICTURE (child), paintable); GstElement *element = g_value_get_object (&value);
g_object_unref (paintable); if (GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_FLAG_SINK))
widget = _get_widget_from_video_sink (element);
g_value_unset (&value);
if (widget)
break;
}
gst_iterator_free (iter);
} }
gst_object_unref (vsink); gst_object_unref (vsink);
} }
if (!child) { if (!widget) {
/* FIXME: Create some default widget to show */ /* FIXME: Create some default widget to show */
child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); widget = g_object_ref_sink (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0));
GST_DEBUG_OBJECT (self, "No widget from video sink, using placeholder"); GST_DEBUG_OBJECT (self, "No widget from video sink, using placeholder");
} }
gtk_overlay_set_child (GTK_OVERLAY (self->overlay), child); gtk_overlay_set_child (GTK_OVERLAY (self->overlay), widget);
g_object_unref (widget);
GST_DEBUG_OBJECT (self, "Set new video widget"); GST_DEBUG_OBJECT (self, "Set new video widget");
} }