]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-video-widget.c
Updated Oriya Translation
[empathy.git] / libempathy-gtk / empathy-video-widget.c
index 3723f50d310c182af2c0f2fb8e9c508f8b450241..0f62496decc915c2b6ceab0847834570ea3a6457 100644 (file)
@@ -51,6 +51,10 @@ static guint signals[LAST_SIGNAL] = {0};
 enum {
   PROP_GST_ELEMENT = 1,
   PROP_GST_BUS,
+  PROP_MIN_WIDTH,
+  PROP_MIN_HEIGHT,
+  PROP_SYNC,
+  PROP_ASYNC,
 };
 
 /* private structure */
@@ -64,22 +68,33 @@ struct _EmpathyVideoWidgetPriv
   GstPad *sink_pad;
   GstElement *overlay;
   FsElementAddedNotifier *notifier;
+  gint min_width;
+  gint min_height;
+  gboolean sync;
+  gboolean async;
+
+  GMutex *lock;
 };
 
 #define GET_PRIV(o)     (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
-  EMPATHY_TYPE_GST_GTK_WIDGET, EmpathyVideoWidgetPriv))
+  EMPATHY_TYPE_VIDEO_WIDGET, EmpathyVideoWidgetPriv))
 
 static void
 empathy_video_widget_init (EmpathyVideoWidget *obj)
 {
   EmpathyVideoWidgetPriv *priv = GET_PRIV (obj);
+  GdkColor black;
+
+  priv->lock = g_mutex_new ();
 
   priv->notifier = fs_element_added_notifier_new ();
   g_signal_connect (priv->notifier, "element-added",
     G_CALLBACK (empathy_video_widget_element_added_cb),
     obj);
 
-  gtk_widget_set_size_request (GTK_WIDGET (obj), 320, 240);
+  if (gdk_color_parse ("Black", &black))
+    gtk_widget_modify_bg (GTK_WIDGET (obj), GTK_STATE_NORMAL,
+      &black);
 
   GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (obj), GTK_DOUBLE_BUFFERED);
 }
@@ -88,25 +103,64 @@ static void
 empathy_video_widget_constructed (GObject *object)
 {
   EmpathyVideoWidgetPriv *priv = GET_PRIV (object);
+  GstElement *colorspace, *videoscale, *sink;
+  GstPad *pad;
+
+  priv->videosink = gst_bin_new (NULL);
 
-  priv->videosink = gst_element_factory_make ("gconfvideosink", NULL);
   gst_object_ref (priv->videosink);
   gst_object_sink (priv->videosink);
 
   priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink");
 
+  sink = gst_element_factory_make ("gconfvideosink", NULL);
+  g_assert (sink != NULL);
+
+  videoscale = gst_element_factory_make ("videoscale", NULL);
+  g_assert (videoscale != NULL);
+
+  g_object_set (videoscale, "qos", FALSE, NULL);
+
+  colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
+  g_assert (colorspace != NULL);
+
+  g_object_set (colorspace, "qos", FALSE, NULL);
+
+  gst_bin_add_many (GST_BIN (priv->videosink), colorspace, videoscale,
+    sink, NULL);
+
+  if (!gst_element_link (colorspace, videoscale))
+    g_error ("Failed to link ffmpegcolorspace and videoscale");
+
+  if (!gst_element_link (videoscale, sink))
+    g_error ("Failed to link videoscale and gconfvideosink");
+
+  pad = gst_element_get_static_pad (colorspace, "sink");
+  g_assert (pad != NULL);
+
+  priv->sink_pad = gst_ghost_pad_new ("sink", pad);
+  if (!gst_element_add_pad  (priv->videosink, priv->sink_pad))
+    g_error ("Couldn't add sink ghostpad to the bin");
+
+  gst_object_unref (pad);
+
   fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink));
   gst_bus_enable_sync_message_emission (priv->bus);
 
   g_signal_connect (priv->bus, "sync-message",
     G_CALLBACK (empathy_video_widget_sync_message_cb), object);
 
+  gtk_widget_set_size_request (GTK_WIDGET (object), priv->min_width,
+    priv->min_height);
 }
 
 static void empathy_video_widget_dispose (GObject *object);
 static void empathy_video_widget_finalize (GObject *object);
+
 static gboolean empathy_video_widget_expose_event (GtkWidget *widget,
   GdkEventExpose *event);
+static void
+empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self);
 
 static void
 empathy_video_widget_set_property (GObject *object,
@@ -119,6 +173,22 @@ empathy_video_widget_set_property (GObject *object,
       case PROP_GST_BUS:
         priv->bus = g_value_dup_object (value);
         break;
+      case PROP_MIN_WIDTH:
+        priv->min_width = g_value_get_int (value);
+        break;
+      case PROP_MIN_HEIGHT:
+        priv->min_height = g_value_get_int (value);
+        break;
+      case PROP_SYNC:
+        priv->sync = g_value_get_boolean (value);
+        empathy_video_widget_element_set_sink_properties (
+          EMPATHY_VIDEO_WIDGET (object));
+        break;
+      case PROP_ASYNC:
+        priv->async = g_value_get_boolean (value);
+        empathy_video_widget_element_set_sink_properties (
+          EMPATHY_VIDEO_WIDGET (object));
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -138,6 +208,18 @@ empathy_video_widget_get_property (GObject *object,
       case PROP_GST_BUS:
         g_value_set_object (value, priv->bus);
         break;
+      case PROP_MIN_WIDTH:
+        g_value_set_int (value, priv->min_width);
+        break;
+      case PROP_MIN_HEIGHT:
+        g_value_set_int (value, priv->min_height);
+        break;
+      case PROP_SYNC:
+        g_value_set_boolean (value, priv->sync);
+        break;
+      case PROP_ASYNC:
+        g_value_set_boolean (value, priv->async);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
     }
@@ -177,6 +259,34 @@ empathy_video_widget_class_init (
     GST_TYPE_BUS,
     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
   g_object_class_install_property (object_class, PROP_GST_BUS, param_spec);
+
+  param_spec = g_param_spec_int ("min-width",
+    "min-width",
+    "Minimal width of the widget",
+    0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH,
+    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_MIN_WIDTH, param_spec);
+
+  param_spec = g_param_spec_int ("min-height",
+    "min-height",
+    "Minimal height of the widget",
+    0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT,
+    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_MIN_HEIGHT, param_spec);
+
+  param_spec = g_param_spec_boolean ("sync",
+    "sync",
+    "Whether the underlying sink should be sync or not",
+    TRUE,
+    G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_SYNC, param_spec);
+
+  param_spec = g_param_spec_boolean ("async",
+    "async",
+    "Whether the underlying sink should be async or not",
+    TRUE,
+    G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (object_class, PROP_ASYNC, param_spec);
 }
 
 void
@@ -190,6 +300,9 @@ empathy_video_widget_dispose (GObject *object)
 
   priv->dispose_has_run = TRUE;
 
+  g_signal_handlers_disconnect_by_func (priv->bus,
+    empathy_video_widget_sync_message_cb, object);
+
   if (priv->bus != NULL)
     g_object_unref (priv->bus);
 
@@ -210,31 +323,65 @@ empathy_video_widget_dispose (GObject *object)
 void
 empathy_video_widget_finalize (GObject *object)
 {
-  //EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
-  //EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+  EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object);
+  EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
 
   /* free any data held directly by the object here */
+  g_mutex_free (priv->lock);
 
   G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object);
 }
 
+
+static void
+empathy_video_widget_element_set_sink_properties_unlocked (
+  EmpathyVideoWidget *self)
+{
+  EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+
+  if (priv->overlay == NULL)
+    return;
+
+  if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay),
+      "force-aspect-ratio"))
+    g_object_set (G_OBJECT (priv->overlay), "force-aspect-ratio", TRUE, NULL);
+
+  if (g_object_class_find_property (
+      G_OBJECT_GET_CLASS (priv->overlay), "sync"))
+    g_object_set (G_OBJECT (priv->overlay), "sync", priv->sync, NULL);
+
+  if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay),
+      "async"))
+    g_object_set (G_OBJECT (priv->overlay), "async", priv->async, NULL);
+}
+
+static void
+empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self)
+{
+  EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
+
+  g_mutex_lock (priv->lock);
+  empathy_video_widget_element_set_sink_properties_unlocked (self);
+  g_mutex_unlock (priv->lock);
+}
+
 static void
 empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier,
   GstBin *bin, GstElement *element, EmpathyVideoWidget *self)
 {
   EmpathyVideoWidgetPriv *priv = GET_PRIV (self);
 
+  /* We assume the overlay is the sink */
+  g_mutex_lock (priv->lock);
   if (priv->overlay == NULL && GST_IS_X_OVERLAY (element))
     {
       priv->overlay = element;
+      g_object_add_weak_pointer (G_OBJECT (element),
+        (gpointer) &priv->overlay);
+      empathy_video_widget_element_set_sink_properties_unlocked (self);
       gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
     }
-
-  if (g_object_class_find_property (
-      G_OBJECT_GET_CLASS (element), "force-aspect-ratio"))
-    {
-      g_object_set (G_OBJECT (element), "force-aspect-ratio", TRUE, NULL);
-    }
+  g_mutex_unlock (priv->lock);
 }
 
 static void
@@ -254,8 +401,9 @@ empathy_video_widget_sync_message_cb (GstBus *bus, GstMessage *message,
 
   if (gst_structure_has_name (s, "prepare-xwindow-id"))
     {
+      g_assert (GTK_WIDGET_REALIZED (GTK_WIDGET (self)));
       gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
-        GDK_WINDOW_XID (GTK_WIDGET (self)->window));
+        GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (self))));
     }
 }
 
@@ -269,23 +417,38 @@ empathy_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event)
     return TRUE;
 
   if (priv->overlay == NULL)
-    return TRUE;
+    {
+      gdk_window_clear_area (gtk_widget_get_window (widget), 0, 0,
+        widget->allocation.width, widget->allocation.height);
+      return TRUE;
+    }
 
   gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay),
-    GDK_WINDOW_XID (widget->window));
+    GDK_WINDOW_XID (gtk_widget_get_window (widget)));
 
   gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay));
 
   return TRUE;
 }
 
+GtkWidget *
+empathy_video_widget_new_with_size (GstBus *bus, gint width, gint height)
+{
+  g_return_val_if_fail (bus != NULL, NULL);
+
+  return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET,
+    "gst-bus", bus,
+    "min-width", width,
+    "min-height", height,
+    NULL));
+}
 
 GtkWidget *
 empathy_video_widget_new (GstBus *bus)
 {
   g_return_val_if_fail (bus != NULL, NULL);
 
-  return GTK_WIDGET (g_object_new (EMPATHY_TYPE_GST_GTK_WIDGET,
+  return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET,
     "gst-bus", bus,
     NULL));
 }