[cheese/cheese-next] Show a timer when recording a video



commit 03222e034b0a7cfe119375f3bc0c8f397c3352e3
Author: Patricia Santana Cruz <patriciasantanacruz gmail com>
Date:   Thu Mar 8 13:16:54 2012 +0000

    Show a timer when recording a video
    
    Fixes bug 599729.

 data/cheese-viewport.json   |   11 +++++++++
 libcheese/cheese-camera.c   |   52 +++++++++++++++++++++++++++++++++++++++++++
 libcheese/cheese-camera.h   |    1 +
 src/cheese-window.vala      |   38 ++++++++++++++++++++++++++++++-
 src/vapi/cheese-common.vapi |    1 +
 5 files changed, 102 insertions(+), 1 deletions(-)
---
diff --git a/data/cheese-viewport.json b/data/cheese-viewport.json
index da75cf2..f714b14 100644
--- a/data/cheese-viewport.json
+++ b/data/cheese-viewport.json
@@ -33,6 +33,17 @@
   "visible": false
 },
 {
+  "id": "timeout_layer",
+  "type": "ClutterText",
+  "color": "White",
+  "font-name": "Sans bold 15px",
+  "x": 0,
+  "y": 0,
+  "width":100,
+  "height":20,
+  "visible": false
+},
+{
   "id": "viewport_layout",
   "type": "ClutterBox",
   "children":
diff --git a/libcheese/cheese-camera.c b/libcheese/cheese-camera.c
index 8e6d8fc..fefd954 100644
--- a/libcheese/cheese-camera.c
+++ b/libcheese/cheese-camera.c
@@ -1742,3 +1742,55 @@ cheese_camera_set_balance_property (CheeseCamera *camera, const gchar *property,
 
   g_object_set (G_OBJECT (priv->video_balance), property, value, NULL);
 }
+
+/**
+ * cheese_camera_get_recorded_time:
+ * @camera: A #CheeseCamera
+ *
+ * Get a string representation of the playing time
+ * of the current video recording
+ *
+ * Returns: A string with the time representation.
+ */
+gchar *
+cheese_camera_get_recorded_time (CheeseCamera *camera)
+{
+  g_return_val_if_fail (CHEESE_IS_CAMERA (camera), NULL);
+
+  CheeseCameraPrivate *priv = camera->priv;
+  const gint TUNIT_60 = 60;
+  GstClock *clock;
+  GstClockTime base_time;
+  GstClockTime clock_time;
+  GstClockTimeDiff time_diff;
+  gint total_time;
+  gint hours;
+  gint minutes;
+  gint seconds;
+
+  base_time  = gst_element_get_base_time (priv->camerabin);
+  clock = gst_element_get_clock (priv->camerabin);
+  clock_time = gst_clock_get_time (clock);
+  gst_object_unref (clock);
+  /* In order to calculate the running time of the stream,
+   * it is necessary to substract the base_time from the
+   * clock_time. The result is expressed in nanoseconds.
+   * */
+  time_diff = GST_CLOCK_DIFF (base_time, clock_time);
+
+  // Substract seconds, minutes and hours.
+  total_time = GST_TIME_AS_SECONDS (time_diff);
+  seconds = total_time % TUNIT_60;
+  total_time = total_time - seconds;
+  minutes = (total_time % (TUNIT_60 * TUNIT_60)) / TUNIT_60;
+  total_time = total_time - (minutes * TUNIT_60);
+  hours = total_time / (TUNIT_60 * TUNIT_60);
+
+  /* Translators: This is a time format, like "09:05:02" for 9
+   * hours, 5 minutes, and 2 seconds. You may change ":" to
+   * the separator that your locale uses or use "%Id" instead
+   * of "%d" if your locale uses localized digits.
+   */
+  return g_strdup_printf (C_("time format", "%02i:%02i:%02i"),
+                          hours, minutes, seconds);
+}
diff --git a/libcheese/cheese-camera.h b/libcheese/cheese-camera.h
index bfc9525..2969a4c 100644
--- a/libcheese/cheese-camera.h
+++ b/libcheese/cheese-camera.h
@@ -125,6 +125,7 @@ gboolean cheese_camera_get_balance_property_range (CheeseCamera *camera,
                                                    gdouble *min, gdouble *max, gdouble *def);
 void cheese_camera_set_balance_property (CheeseCamera *camera, const gchar *property, gdouble value);
 void cheese_camera_toggle_effects_pipeline (CheeseCamera *camera, gboolean active);
+gchar *cheese_camera_get_recorded_time (CheeseCamera *camera);
 
 G_END_DECLS
 
diff --git a/src/cheese-window.vala b/src/cheese-window.vala
index 12ef2e0..919d754 100644
--- a/src/cheese-window.vala
+++ b/src/cheese-window.vala
@@ -74,6 +74,7 @@ public class Cheese.MainWindow : Gtk.Window
   private Clutter.Text      countdown_layer;
   private Clutter.Rectangle background_layer;
   private Clutter.Text      error_layer;
+  private Clutter.Text      timeout_layer;
 
   private Clutter.Box           current_effects_grid;
   private int                current_effects_page = 0;
@@ -680,7 +681,9 @@ public class Cheese.MainWindow : Gtk.Window
     
     if (preferences_dialog != null)
       preferences_dialog.set_current_mode (current_mode);
-    
+
+    timeout_layer.hide ();
+
     switch (this.current_mode)
     {
       case MediaMode.PHOTO:
@@ -695,6 +698,8 @@ public class Cheese.MainWindow : Gtk.Window
         take_video_action.sensitive       = true;
         take_burst_action.sensitive       = false;
         take_action_button.related_action = take_video_action;
+        timeout_layer.text = "00:00:00";
+        timeout_layer.show ();
         break;
 
       case MediaMode.BURST:
@@ -886,6 +891,8 @@ public class Cheese.MainWindow : Gtk.Window
   {
     this.viewport_layout.set_size (viewport.width, viewport.height);
     this.background_layer.set_size (viewport.width, viewport.height);
+    this.timeout_layer.set_position (video_preview.width/3 + viewport.width/2,
+                                viewport.height-20);
   }
 
   /**
@@ -1024,6 +1031,10 @@ public class Cheese.MainWindow : Gtk.Window
     if (is_start)
     {
       camera.start_video_recording (fileutil.get_new_media_filename (this.current_mode));
+      /* Will be called every 1 second while
+       * update_timeout_layer returns true.
+       */
+      Timeout.add_seconds (1, update_timeout_layer);
       take_action_button_label.label = "<b>" + _("Stop _Recording") + "</b>";
       take_action_button.tooltip_text = _("Stop recording");
       take_action_button_image.set_from_stock (Gtk.Stock.MEDIA_STOP, Gtk.IconSize.BUTTON);
@@ -1033,6 +1044,13 @@ public class Cheese.MainWindow : Gtk.Window
     else
     {
       camera.stop_video_recording ();
+      /* The timeout_layer always shows the "00:00:00"
+       * string when not recording, in order to notify
+       * the user about two things:
+       *   + The user is making use of the recording mode.
+       *   + The user is currently not recording.
+       */
+      timeout_layer.text = "00:00:00";
       take_action_button_label.label = "<b>" + take_action_button.related_action.label + "</b>";
       take_action_button.tooltip_text = take_action_button.related_action.tooltip;
       take_action_button_image.set_from_stock (Gtk.Stock.MEDIA_RECORD, Gtk.IconSize.BUTTON);
@@ -1042,6 +1060,22 @@ public class Cheese.MainWindow : Gtk.Window
   }
 
   /**
+   * Update the timeout layer displayed timer.
+   *
+   * @return false, if the source, Timeout.add_seconds (used
+   * in the toogle_video_recording method), should be removed.
+   */
+  private bool update_timeout_layer ()
+  {
+    if (is_recording) {
+      timeout_layer.text = camera.get_recorded_time ();
+      return true;
+    }
+    else
+      return false;
+  }
+
+  /**
    * Toggle whether photo bursting is active.
    *
    * @param is_start whether to start capturing a photo burst
@@ -1522,6 +1556,7 @@ public class Cheese.MainWindow : Gtk.Window
     countdown_layer         = clutter_builder.get_object ("countdown_layer") as Clutter.Text;
     background_layer        = clutter_builder.get_object ("background") as Clutter.Rectangle;
     error_layer             = clutter_builder.get_object ("error_layer") as Clutter.Text;
+    timeout_layer           = clutter_builder.get_object ("timeout_layer") as Clutter.Text;
 
     video_preview.keep_aspect_ratio = true;
     video_preview.request_mode      = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
@@ -1529,6 +1564,7 @@ public class Cheese.MainWindow : Gtk.Window
     viewport_layout.set_layout_manager (viewport_layout_manager);
 
     viewport.add_actor (viewport_layout);
+    viewport.add_actor (timeout_layer);
 
     viewport.allocation_changed.connect (on_stage_resize);
 
diff --git a/src/vapi/cheese-common.vapi b/src/vapi/cheese-common.vapi
index 5b59b0d..075b594 100644
--- a/src/vapi/cheese-common.vapi
+++ b/src/vapi/cheese-common.vapi
@@ -56,6 +56,7 @@ namespace Cheese
     public bool                        switch_camera_device ();
     public bool                        take_photo (string filename);
     public bool                        take_photo_pixbuf ();
+    public string                      get_recorded_time ();
     [NoAccessorMethod]
     public string device_node {owned get; set;}
     [NoAccessorMethod]



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