[empathy: 5/8] Added an early return in empathy_call_window_setup_video_preview.



commit 3719c62c3f34e11dbdcdff741eb2aadf69c9c202
Author: Jonathan Tellier <jonathan tellier gmail com>
Date:   Thu Jun 11 10:12:26 2009 -0400

    Added an early return in empathy_call_window_setup_video_preview.
    Code style correction in
    empathy_call_window_setup_video_preview_visibility.
    Corrected a bug which prevented a user with no video input to redial
    video calls.
    The "Send video" option should be properly disabled when we can't send
    video.

 libempathy-gtk/empathy-video-widget.c |    3 +
 src/empathy-call-window.c             |  183 +++++++++++++++++----------------
 2 files changed, 99 insertions(+), 87 deletions(-)
---
diff --git a/libempathy-gtk/empathy-video-widget.c b/libempathy-gtk/empathy-video-widget.c
index 7647b84..79f2781 100644
--- a/libempathy-gtk/empathy-video-widget.c
+++ b/libempathy-gtk/empathy-video-widget.c
@@ -300,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);
 
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index 7bf9c5d..4b4f53f 100644
--- a/src/empathy-call-window.c
+++ b/src/empathy-call-window.c
@@ -62,6 +62,9 @@
 
 #define CONNECTING_STATUS_TEXT _("Connecting...")
 
+/* If an video input error occurs, the error message will start with "v4l" */
+#define VIDEO_INPUT_ERROR_PREFIX "v4l"
+
 G_DEFINE_TYPE(EmpathyCallWindow, empathy_call_window, GTK_TYPE_WINDOW)
 
 /* signal enum */
@@ -187,6 +190,9 @@ static void empathy_call_window_sidebar_toggled_cb (GtkToggleButton *toggle,
 static void empathy_call_window_camera_toggled_cb (GtkToggleToolButton *toggle,
   EmpathyCallWindow *window);
 
+static void empathy_call_window_set_send_video (EmpathyCallWindow *window,
+  gboolean send);
+
 static void empathy_call_window_send_video_toggled_cb (GtkToggleAction *toggle,
   EmpathyCallWindow *window);
 
@@ -606,34 +612,40 @@ empathy_call_window_setup_video_preview (EmpathyCallWindow *window)
 {
   EmpathyCallWindowPriv *priv = GET_PRIV (window);
 
-  if (priv->video_tee == NULL && priv->video_preview == NULL)
+  if (priv->video_preview != NULL)
     {
-      GstElement *preview;
-      GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline));
-
-      priv->video_tee = gst_element_factory_make ("tee", NULL);
-      gst_object_ref (priv->video_tee);
-      gst_object_sink (priv->video_tee);
-
-      priv->video_preview = empathy_video_widget_new_with_size (bus,
-          SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH);
-      g_object_set (priv->video_preview, "sync", FALSE, "async", TRUE, NULL);
-      gtk_box_pack_start (GTK_BOX (priv->self_user_output_hbox),
-          priv->video_preview, TRUE, TRUE, 0);
-
-      preview = empathy_video_widget_get_element (
-          EMPATHY_VIDEO_WIDGET (priv->video_preview));
-      gst_bin_add_many (GST_BIN (priv->pipeline), priv->video_input,
-          priv->video_tee, preview, NULL);
-      gst_element_link_many (priv->video_input, priv->video_tee,
-          preview, NULL);
-
-      g_object_unref (bus);
-
-      gst_element_set_state (preview, GST_STATE_PLAYING);
-      gst_element_set_state (priv->video_input, GST_STATE_PLAYING);
-      gst_element_set_state (priv->video_tee, GST_STATE_PLAYING);
+      /* Since the video preview and the video tee are initialized and freed
+         at the same time, if one is initialized, then the other one should
+         be too. */
+      g_assert (priv->video_tee != NULL);
+      return;
     }
+
+    GstElement *preview;
+    GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline));
+
+    priv->video_tee = gst_element_factory_make ("tee", NULL);
+    gst_object_ref (priv->video_tee);
+    gst_object_sink (priv->video_tee);
+
+    priv->video_preview = empathy_video_widget_new_with_size (bus,
+        SELF_VIDEO_SECTION_WIDTH, SELF_VIDEO_SECTION_HEIGTH);
+    g_object_set (priv->video_preview, "sync", FALSE, "async", TRUE, NULL);
+    gtk_box_pack_start (GTK_BOX (priv->self_user_output_hbox),
+        priv->video_preview, TRUE, TRUE, 0);
+
+    preview = empathy_video_widget_get_element (
+        EMPATHY_VIDEO_WIDGET (priv->video_preview));
+    gst_bin_add_many (GST_BIN (priv->pipeline), priv->video_input,
+        priv->video_tee, preview, NULL);
+    gst_element_link_many (priv->video_input, priv->video_tee,
+        preview, NULL);
+
+    g_object_unref (bus);
+
+    gst_element_set_state (preview, GST_STATE_PLAYING);
+    gst_element_set_state (priv->video_input, GST_STATE_PLAYING);
+    gst_element_set_state (priv->video_tee, GST_STATE_PLAYING);
 }
 
 static void
@@ -903,10 +915,14 @@ empathy_call_window_setup_video_preview_visibility (EmpathyCallWindow *self,
     {
       empathy_call_window_setup_video_preview (self);
       gtk_widget_hide (priv->self_user_avatar_widget);
-      gtk_widget_show (priv->video_preview);
+
+      if (priv->video_preview != NULL)
+        gtk_widget_show (priv->video_preview);
     }
   else
+    {
       gtk_widget_show (priv->self_user_avatar_widget);
+    }
 
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview),
       initial_video);
@@ -1131,12 +1147,32 @@ empathy_call_window_reset_pipeline (EmpathyCallWindow *self)
   if (state_change_return == GST_STATE_CHANGE_SUCCESS ||
         state_change_return == GST_STATE_CHANGE_NO_PREROLL)
     {
+      if (priv->pipeline != NULL)
+        g_object_unref (priv->pipeline);
+      priv->pipeline = NULL;
+
+      if (priv->video_input != NULL)
+        g_object_unref (priv->video_input);
+      priv->video_input = NULL;
+
+      if (priv->audio_input != NULL)
+        g_object_unref (priv->audio_input);
+      priv->audio_input = NULL;
+
+      if (priv->audio_output != NULL)
+        g_object_unref (priv->audio_output);
+      priv->audio_output = NULL;
+
+      if (priv->video_tee != NULL)
+        g_object_unref (priv->video_tee);
+      priv->video_tee = NULL;
+
+      if (priv->video_preview != NULL)
+        gtk_widget_destroy (priv->video_preview);
+      priv->video_preview = NULL;
+
       priv->liveadder = NULL;
       priv->funnel = NULL;
-      priv->video_preview = NULL;
-      priv->video_tee = NULL;
-      g_object_unref (priv->pipeline);
-      priv->pipeline = NULL;
 
       return TRUE;
     }
@@ -1287,20 +1323,20 @@ empathy_call_window_connected (gpointer user_data)
   if (empathy_tp_call_has_dtmf (call))
     gtk_widget_set_sensitive (priv->dtmf_panel, TRUE);
 
+  if (priv->video_input == NULL)
+      empathy_call_window_set_send_video (self, FALSE);
+
   priv->sending_video = empathy_tp_call_is_sending_video (call);
 
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->show_preview),
       priv->sending_video);
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video),
-      priv->sending_video);
+      priv->sending_video && priv->video_input != NULL);
   gtk_toggle_tool_button_set_active (
-            GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), priv->sending_video);
-
-  if (priv->video_input != NULL)
-    {
-      gtk_widget_set_sensitive (priv->camera_button, TRUE);
-      gtk_action_set_sensitive (priv->send_video, TRUE);
-    }
+      GTK_TOGGLE_TOOL_BUTTON (priv->camera_button),
+      priv->sending_video && priv->video_input != NULL);
+  gtk_widget_set_sensitive (priv->camera_button, priv->video_input != NULL);
+  gtk_action_set_sensitive (priv->send_video, priv->video_input != NULL);
 
   gtk_action_set_sensitive (priv->redial, FALSE);
   gtk_widget_set_sensitive (priv->redial_button, FALSE);
@@ -1391,8 +1427,10 @@ empathy_call_window_sink_added_cb (EmpathyCallHandler *handler,
                 empathy_call_window_setup_video_preview (self);
 
                 gtk_toggle_action_set_active (
-                    GTK_TOGGLE_ACTION (priv->show_preview),TRUE);
-                gtk_widget_show (priv->video_preview);
+                    GTK_TOGGLE_ACTION (priv->show_preview), TRUE);
+
+                if (priv->video_preview != NULL)
+                  gtk_widget_show (priv->video_preview);
                 gtk_widget_hide (priv->self_user_avatar_widget);
               }
 
@@ -1411,45 +1449,6 @@ empathy_call_window_sink_added_cb (EmpathyCallHandler *handler,
 
 }
 
-static gboolean
-empathy_gst_bin_has_child (GstBin *bin, GstElement *element)
-{
-  GstIterator *it;
-  gboolean ret = FALSE;
-  GstElement *item;
-
-  it = gst_bin_iterate_recurse (bin);
-
-  for (;;)
-    {
-      switch (gst_iterator_next (it, (gpointer *)&item))
-       {
-         case GST_ITERATOR_OK:
-           if (item == element)
-            {
-              gst_object_unref (GST_OBJECT (item));
-              ret = TRUE;
-              goto out;
-            }
-           gst_object_unref (GST_OBJECT (item));
-           break;
-         case GST_ITERATOR_RESYNC:
-           gst_iterator_resync (it);
-           break;
-        case GST_ITERATOR_ERROR:
-           g_assert_not_reached ();
-           /* fallthrough */
-        case GST_ITERATOR_DONE:
-           goto out;
-           break;
-      }
-    }
-    gst_iterator_free (it);
-
-out:
-  return ret;
-}
-
 static void
 empathy_call_window_remove_video_input (EmpathyCallWindow *self)
 {
@@ -1470,8 +1469,15 @@ empathy_call_window_remove_video_input (EmpathyCallWindow *self)
   priv->video_input = NULL;
   g_object_unref (priv->video_tee);
   priv->video_tee = NULL;
+  gtk_widget_destroy (priv->video_preview);
+  priv->video_preview = NULL;
+
+  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priv->send_video), FALSE);
+  gtk_toggle_tool_button_set_active (
+      GTK_TOGGLE_TOOL_BUTTON (priv->camera_button), FALSE);
+  gtk_widget_set_sensitive (priv->camera_button, FALSE);
+  gtk_action_set_sensitive (priv->send_video, FALSE);
 
-  gtk_widget_hide (priv->video_preview);
   gtk_widget_show (priv->self_user_avatar_widget);
 }
 
@@ -1510,19 +1516,21 @@ empathy_call_window_bus_message (GstBus *bus, GstMessage *message,
       case GST_MESSAGE_ERROR:
         {
           GError *error = NULL;
+          GstElement *gst_error;
           gchar *debug;
 
           gst_message_parse_error (message, &error, &debug);
+          gst_error = GST_ELEMENT (GST_MESSAGE_SRC (message));
 
           g_message ("Element error: %s -- %s\n", error->message, debug);
 
-          if (priv->video_input != NULL &&
-              empathy_gst_bin_has_child (GST_BIN (priv->video_input),
-                GST_ELEMENT (GST_MESSAGE_SRC (message))))
+          if (g_str_has_prefix (gst_element_get_name (gst_error),
+                VIDEO_INPUT_ERROR_PREFIX))
             {
               /* Remove the video input and continue */
-              empathy_call_window_remove_video_input (self);
-              gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
+              if (priv->video_input != NULL)
+                empathy_call_window_remove_video_input (self);
+              gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
             }
           else
             {
@@ -1557,7 +1565,8 @@ empathy_call_window_update_avatars_visibility (EmpathyTpCall *call,
 
   if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (priv->show_preview)))
     {
-      if (empathy_tp_call_is_sending_video (call))
+      if (priv->video_preview != NULL
+          && empathy_tp_call_is_sending_video (call))
         {
           gtk_widget_hide (priv->self_user_avatar_widget);
           gtk_widget_show (priv->video_preview);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]