From: Brandon Philips <bphilips@suse.de>
Subject: cheese: fix double click issue
References: bnc#677668

The force stop method causes Cheese to freeze in some circumstances. In
this particular circumstance it is when a user double clicks the record
button.  The fix is two fold:

- Quickly set disable the button click callback via set sensitive
- Don't let the user click the button again until the save_queue is
  PLAYING. 

Signed-off-by: Brandon Philips <bphilips@suse.de>

---
 src/cheese-webcam.c |   17 +++++++++++++++++
 src/cheese-webcam.h |    1 +
 src/cheese-window.c |   49 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 59 insertions(+), 8 deletions(-)

Index: cheese-2.28.1/src/cheese-webcam.c
===================================================================
--- cheese-2.28.1.orig/src/cheese-webcam.c
+++ cheese-2.28.1/src/cheese-webcam.c
@@ -111,6 +111,7 @@ enum
 {
   PHOTO_SAVED,
   VIDEO_SAVED,
+  VIDEO_PLAYING,
   LAST_SIGNAL
 };
 
@@ -274,6 +275,19 @@ cheese_webcam_bus_message_cb (GstBus *bu
       priv->is_recording = FALSE;
     }
   }
+  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_STATE_CHANGED)
+  {
+    if (strcmp (GST_MESSAGE_SRC_NAME (message), "save_queue") == 0)
+    {
+      g_print ("Received save_queue message\n");
+      GstState old, new;
+      gst_message_parse_state_changed (message, &old, &new, NULL);
+      if (new == GST_STATE_PLAYING) {
+      	 g_print ("Received save_queue PLAYING message\n");
+        g_signal_emit (webcam, webcam_signals[VIDEO_PLAYING], 0, new);
+      }
+    }
+  }
 }
 
 static void
@@ -1558,6 +1572,12 @@ cheese_webcam_class_init (CheeseWebcamCl
                                               g_cclosure_marshal_VOID__VOID,
                                               G_TYPE_NONE, 0);
 
+  webcam_signals[VIDEO_PLAYING] = g_signal_new ("video-playing", G_OBJECT_CLASS_TYPE (klass),
+                                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                              G_STRUCT_OFFSET (CheeseWebcamClass, video_playing),
+                                              NULL, NULL,
+                                              g_cclosure_marshal_VOID__VOID,
+                                              G_TYPE_NONE, 0);
 
   g_object_class_install_property (object_class, PROP_VIDEO_WINDOW,
                                    g_param_spec_pointer ("video-window",
Index: cheese-2.28.1/src/cheese-webcam.h
===================================================================
--- cheese-2.28.1.orig/src/cheese-webcam.h
+++ cheese-2.28.1/src/cheese-webcam.h
@@ -92,6 +92,7 @@ typedef struct
   GObjectClass parent_class;
   void (*photo_saved) (CheeseWebcam *webcam);
   void (*video_saved) (CheeseWebcam *webcam);
+  void (*video_playing) (CheeseWebcam *webcam);
 } CheeseWebcamClass;
 
 
Index: cheese-2.28.1/src/cheese-window.c
===================================================================
--- cheese-2.28.1.orig/src/cheese-window.c
+++ cheese-2.28.1/src/cheese-window.c
@@ -84,6 +84,7 @@ typedef enum
 typedef struct
 {
   gboolean recording;
+  gboolean video_save_started;
 
   gboolean isFullscreen;
 
@@ -155,6 +156,7 @@ typedef struct
   GtkWidget *screen;
   GtkWidget *take_picture;
   GtkWidget *take_picture_fullscreen;
+  guint idle_id;
 
   GtkActionGroup *actions_account_photo;
   GtkActionGroup *actions_countdown;
@@ -492,11 +494,26 @@ cheese_window_video_saved_cb (CheeseWebc
   gtk_action_group_set_sensitive (cheese_window->actions_effects, TRUE);
   gtk_widget_set_sensitive (cheese_window->take_picture, TRUE);
   gtk_widget_set_sensitive (cheese_window->take_picture_fullscreen, TRUE);
+  cheese_window->video_save_started = FALSE;
   gdk_flush ();
   gdk_threads_leave ();
 }
 
 static void
+cheese_window_video_playing_cb (CheeseWebcam *webcam, CheeseWindow *cheese_window)
+{
+  gdk_threads_enter ();
+  g_print ("playing_cb()\n");
+  if (cheese_window->recording == TRUE) 
+  {
+    cheese_window->video_save_started = TRUE;
+    gtk_widget_set_sensitive (cheese_window->take_picture, TRUE);
+    gtk_widget_set_sensitive (cheese_window->take_picture_fullscreen, TRUE);
+  }
+  gdk_threads_leave ();
+}
+
+static void
 cheese_window_cmd_close (GtkWidget *widget, CheeseWindow *cheese_window)
 {
   g_object_unref (cheese_window->webcam);
@@ -1463,6 +1481,22 @@ cheese_window_take_photo (gpointer data)
   return FALSE;
 }
 
+static gboolean
+start_video_idle_cb (gpointer data)
+{
+  CheeseWindow *cheese_window = data;
+
+  cheese_window->video_filename = cheese_fileutil_get_new_media_filename (cheese_window->fileutil,
+									  WEBCAM_MODE_VIDEO);
+  cheese_webcam_start_video_recording (cheese_window->webcam, cheese_window->video_filename);
+
+  cheese_window->idle_id = 0;
+  cheese_window->recording = TRUE;
+
+  /* don't call this again */
+  return FALSE;
+}
+
 static void
 cheese_window_action_button_clicked_cb (GtkWidget *widget, CheeseWindow *cheese_window)
 {
@@ -1484,10 +1518,13 @@ cheese_window_action_button_clicked_cb (
       cheese_window_take_photo (cheese_window);
       break;
     case WEBCAM_MODE_VIDEO:
-      if (!cheese_window->recording)
+      if (!cheese_window->recording && !cheese_window->idle_id)
       {
+        g_print ("starting recording thread and doing UI stuff() %p\n", widget);
         gtk_action_group_set_sensitive (cheese_window->actions_effects, FALSE);
         gtk_action_group_set_sensitive (cheese_window->actions_toggle, FALSE);
+        gtk_widget_set_sensitive (cheese_window->take_picture, FALSE);
+        gtk_widget_set_sensitive (cheese_window->take_picture_fullscreen, FALSE);
         str = g_strconcat ("<b>", _("_Stop Recording"), "</b>", NULL);
         gtk_label_set_text_with_mnemonic (GTK_LABEL (cheese_window->label_take_photo), str);
         gtk_label_set_text_with_mnemonic (GTK_LABEL (cheese_window->label_take_photo_fullscreen), str);
@@ -1498,15 +1535,11 @@ cheese_window_action_button_clicked_cb (
         gtk_label_set_use_markup (GTK_LABEL (cheese_window->label_take_photo_fullscreen), TRUE);
         gtk_image_set_from_stock (GTK_IMAGE (cheese_window->image_take_photo_fullscreen),
                                   GTK_STOCK_MEDIA_STOP, GTK_ICON_SIZE_BUTTON);
-
-        cheese_window->video_filename = cheese_fileutil_get_new_media_filename (cheese_window->fileutil,
-                                                                                WEBCAM_MODE_VIDEO);
-        cheese_webcam_start_video_recording (cheese_window->webcam, cheese_window->video_filename);
-
-        cheese_window->recording = TRUE;
+        cheese_window->idle_id = gdk_threads_add_idle (start_video_idle_cb, cheese_window);
       }
-      else
+      else if (cheese_window->recording && cheese_window->video_save_started) /* let the video start before stopping again */
       {
+        g_print ("cheese_window_stop_recording() %p\n", widget);
         cheese_window_stop_recording (cheese_window);
       }
       break;
@@ -2090,6 +2123,8 @@ setup_camera (CheeseWindow *cheese_windo
                     G_CALLBACK (cheese_window_photo_saved_cb), cheese_window);
   g_signal_connect (cheese_window->webcam, "video-saved",
                     G_CALLBACK (cheese_window_video_saved_cb), cheese_window);
+  g_signal_connect (cheese_window->webcam, "video-playing",
+                    G_CALLBACK (cheese_window_video_playing_cb), cheese_window);
 
   cheese_webcam_set_effect (cheese_window->webcam,
                             cheese_effect_chooser_get_selection (CHEESE_EFFECT_CHOOSER (cheese_window->effect_chooser)));
@@ -2136,6 +2171,7 @@ cheese_window_init (char *hal_dev_udi, C
   cheese_window->audio_play_counter  = 0;
   cheese_window->isFullscreen        = FALSE;
   cheese_window->is_bursting         = FALSE;
+  cheese_window->idle_id             = 0;
 
   cheese_window->server = dbus_server;
 
@@ -2153,6 +2189,7 @@ cheese_window_init (char *hal_dev_udi, C
 
   cheese_window->webcam_mode = WEBCAM_MODE_PHOTO;
   cheese_window->recording   = FALSE;
+  cheese_window->video_save_started = FALSE;
 
   g_object_get (cheese_window->gconf,
                 "gconf_prop_wide_mode",
