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 priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink");
95 fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink));
96 gst_bus_enable_sync_message_emission (priv->bus);
98 g_signal_connect (priv->bus, "sync-message",
99 G_CALLBACK (empathy_video_widget_sync_message_cb), object);
103 static void empathy_video_widget_dispose (GObject *object);
104 static void empathy_video_widget_finalize (GObject *object);
105 static gboolean empathy_video_widget_expose_event (GtkWidget *widget,
106 GdkEventExpose *event);
109 empathy_video_widget_set_property (GObject *object,
110 guint property_id, const GValue *value, GParamSpec *pspec)
112 EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
117 priv->bus = g_value_dup_object (value);
120 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
125 empathy_video_widget_get_property (GObject *object,
126 guint property_id, GValue *value, GParamSpec *pspec)
128 EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
132 case PROP_GST_ELEMENT:
133 g_value_set_object (value, priv->videosink);
136 g_value_set_object (value, priv->bus);
139 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
145 empathy_video_widget_class_init (
146 EmpathyVideoWidgetClass *empathy_video_widget_class)
148 GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_widget_class);
149 GtkWidgetClass *widget_class =
150 GTK_WIDGET_CLASS (empathy_video_widget_class);
151 GParamSpec *param_spec;
153 g_type_class_add_private (empathy_video_widget_class,
154 sizeof (EmpathyVideoWidgetPriv));
156 object_class->dispose = empathy_video_widget_dispose;
157 object_class->finalize = empathy_video_widget_finalize;
158 object_class->constructed = empathy_video_widget_constructed;
160 object_class->set_property = empathy_video_widget_set_property;
161 object_class->get_property = empathy_video_widget_get_property;
163 widget_class->expose_event = empathy_video_widget_expose_event;
165 param_spec = g_param_spec_object ("gst-element",
166 "gst-element", "The underlaying gstreamer element",
168 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
169 g_object_class_install_property (object_class, PROP_GST_ELEMENT, param_spec);
171 param_spec = g_param_spec_object ("gst-bus",
173 "The toplevel bus from the pipeline in which this bin will be added",
175 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
176 g_object_class_install_property (object_class, PROP_GST_BUS, param_spec);
180 empathy_video_widget_dispose (GObject *object)
182 EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
183 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
185 if (priv->dispose_has_run)
188 priv->dispose_has_run = TRUE;
190 if (priv->bus != NULL)
191 g_object_unref (priv->bus);
195 /* release any references held by the object here */
197 if (G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose)
198 G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose (object);
202 empathy_video_widget_finalize (GObject *object)
204 //EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
205 //EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
207 /* free any data held directly by the object here */
209 G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object);
213 empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier,
214 GstBin *bin, GstElement *element, EmpathyVideoWidget *self)
216 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
218 if (priv->overlay == NULL && GST_IS_X_OVERLAY (element))
220 priv->overlay = element;
221 gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
224 if (g_object_class_find_property (
225 G_OBJECT_GET_CLASS (element), "force-aspect-ratio"))
227 g_object_set (G_OBJECT (element), "force-aspect-ratio", TRUE, NULL);
232 empathy_video_widget_sync_message_cb (GstBus *bus, GstMessage *message,
233 EmpathyVideoWidget *self)
235 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
236 const GstStructure *s;
238 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
241 if (GST_MESSAGE_SRC (message) != (GstObject *) priv->overlay)
244 s = gst_message_get_structure (message);
246 if (gst_structure_has_name (s, "prepare-xwindow-id"))
248 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
249 GDK_WINDOW_XID (GTK_WIDGET (self)->window));
254 empathy_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event)
256 EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (widget);
257 EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
259 if (event != NULL && event->count > 0)
262 if (priv->overlay == NULL)
265 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
266 GDK_WINDOW_XID (widget->window));
268 gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
275 empathy_video_widget_new (GstBus *bus)
277 g_return_val_if_fail (bus != NULL, NULL);
279 return GTK_WIDGET (g_object_new (EMPATHY_TYPE_GST_GTK_WIDGET,
285 empathy_video_widget_get_sink (EmpathyVideoWidget *widget)
287 EmpathyVideoWidgetPriv *priv = GET_PRIV (widget);
289 return priv->sink_pad;
293 empathy_video_widget_get_element (EmpathyVideoWidget *widget)
295 EmpathyVideoWidgetPriv *priv = GET_PRIV (widget);
297 return priv->videosink;