2 * empathy-gst-gtk-widget.c - Source for EmpathyVideoWidget
3 * Copyright (C) 2008 Collabora Ltd.
4 * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <gst/interfaces/xoverlay.h>
27 #include <gst/farsight/fs-element-added-notifier.h>
29 #include "empathy-video-widget.h"
31 G_DEFINE_TYPE(EmpathyVideoWidget, empathy_video_widget,
32 GTK_TYPE_DRAWING_AREA)
34 static void empathy_video_widget_element_added_cb (
35 FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element,
36 EmpathyVideoWidget *self);
38 static void empathy_video_widget_sync_message_cb (
39 GstBus *bus, GstMessage *message, EmpathyVideoWidget *self);
48 static guint signals[LAST_SIGNAL] = {0};
56 /* private structure */
57 typedef struct _EmpathyVideoWidgetPriv EmpathyVideoWidgetPriv;
59 struct _EmpathyVideoWidgetPriv
61 gboolean dispose_has_run;
63 GstElement *videosink;
66 FsElementAddedNotifier *notifier;
69 #define GET_PRIV(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
70 EMPATHY_TYPE_GST_GTK_WIDGET, EmpathyVideoWidgetPriv))
73 empathy_video_widget_init (EmpathyVideoWidget *obj)
75 EmpathyVideoWidgetPriv *priv = GET_PRIV (obj);
77 priv->notifier = fs_element_added_notifier_new ();
78 g_signal_connect (priv->notifier, "element-added",
79 G_CALLBACK (empathy_video_widget_element_added_cb),
82 gtk_widget_set_size_request (GTK_WIDGET (obj), 320, 240);
84 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (obj), GTK_DOUBLE_BUFFERED);
88 empathy_video_widget_constructed (GObject *object)
90 EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
92 priv->videosink = gst_element_factory_make ("gconfvideosink", NULL);
93 gst_object_ref (priv->videosink);
94 gst_object_sink (priv->videosink);
96 priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink");
98 fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink));
99 gst_bus_enable_sync_message_emission (priv->bus);
101 g_signal_connect (priv->bus, "sync-message",
102 G_CALLBACK (empathy_video_widget_sync_message_cb), object);
106 static void empathy_video_widget_dispose (GObject *object);
107 static void empathy_video_widget_finalize (GObject *object);
108 static gboolean empathy_video_widget_expose_event (GtkWidget *widget,
109 GdkEventExpose *event);
112 empathy_video_widget_set_property (GObject *object,
113 guint property_id, const GValue *value, GParamSpec *pspec)
115 EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
120 priv->bus = g_value_dup_object (value);
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
128 empathy_video_widget_get_property (GObject *object,
129 guint property_id, GValue *value, GParamSpec *pspec)
131 EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
135 case PROP_GST_ELEMENT:
136 g_value_set_object (value, priv->videosink);
139 g_value_set_object (value, priv->bus);
142 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
148 empathy_video_widget_class_init (
149 EmpathyVideoWidgetClass *empathy_video_widget_class)
151 GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_widget_class);
152 GtkWidgetClass *widget_class =
153 GTK_WIDGET_CLASS (empathy_video_widget_class);
154 GParamSpec *param_spec;
156 g_type_class_add_private (empathy_video_widget_class,
157 sizeof (EmpathyVideoWidgetPriv));
159 object_class->dispose = empathy_video_widget_dispose;
160 object_class->finalize = empathy_video_widget_finalize;
161 object_class->constructed = empathy_video_widget_constructed;
163 object_class->set_property = empathy_video_widget_set_property;
164 object_class->get_property = empathy_video_widget_get_property;
166 widget_class->expose_event = empathy_video_widget_expose_event;
168 param_spec = g_param_spec_object ("gst-element",
169 "gst-element", "The underlaying gstreamer element",
171 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
172 g_object_class_install_property (object_class, PROP_GST_ELEMENT, param_spec);
174 param_spec = g_param_spec_object ("gst-bus",
176 "The toplevel bus from the pipeline in which this bin will be added",
178 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
179 g_object_class_install_property (object_class, PROP_GST_BUS, param_spec);
183 empathy_video_widget_dispose (GObject *object)
185 EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
186 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
188 if (priv->dispose_has_run)
191 priv->dispose_has_run = TRUE;
193 if (priv->bus != NULL)
194 g_object_unref (priv->bus);
198 if (priv->videosink != NULL)
199 g_object_unref (priv->videosink);
201 priv->videosink = NULL;
204 /* release any references held by the object here */
206 if (G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose)
207 G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose (object);
211 empathy_video_widget_finalize (GObject *object)
213 //EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
214 //EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
216 /* free any data held directly by the object here */
218 G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object);
222 empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier,
223 GstBin *bin, GstElement *element, EmpathyVideoWidget *self)
225 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
227 if (priv->overlay == NULL && GST_IS_X_OVERLAY (element))
229 priv->overlay = element;
230 gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
233 if (g_object_class_find_property (
234 G_OBJECT_GET_CLASS (element), "force-aspect-ratio"))
236 g_object_set (G_OBJECT (element), "force-aspect-ratio", TRUE, NULL);
241 empathy_video_widget_sync_message_cb (GstBus *bus, GstMessage *message,
242 EmpathyVideoWidget *self)
244 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
245 const GstStructure *s;
247 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
250 if (GST_MESSAGE_SRC (message) != (GstObject *) priv->overlay)
253 s = gst_message_get_structure (message);
255 if (gst_structure_has_name (s, "prepare-xwindow-id"))
257 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
258 GDK_WINDOW_XID (GTK_WIDGET (self)->window));
263 empathy_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event)
265 EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (widget);
266 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
268 if (event != NULL && event->count > 0)
271 if (priv->overlay == NULL)
274 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
275 GDK_WINDOW_XID (widget->window));
277 gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
284 empathy_video_widget_new (GstBus *bus)
286 g_return_val_if_fail (bus != NULL, NULL);
288 return GTK_WIDGET (g_object_new (EMPATHY_TYPE_GST_GTK_WIDGET,
294 empathy_video_widget_get_sink (EmpathyVideoWidget *widget)
296 EmpathyVideoWidgetPriv *priv = GET_PRIV (widget);
298 return priv->sink_pad;
302 empathy_video_widget_get_element (EmpathyVideoWidget *widget)
304 EmpathyVideoWidgetPriv *priv = GET_PRIV (widget);
306 return priv->videosink;