2007-10-16 Emmanuele Bassi <ebassi@openedhand.com>
authorEmmanuele Bassi <ebassi@openedhand.com>
Tue, 16 Oct 2007 13:41:34 +0000 (13:41 +0000)
committerEmmanuele Bassi <ebassi@openedhand.com>
Tue, 16 Oct 2007 13:41:34 +0000 (13:41 +0000)
* clutter/clutter-timeline.[ch]: Added ClutterTimeline:duration,
a property for setting the duration of a timeline in milliseconds.
The property comes with accessors and a new constructor. The
frame rate used is the default value.

* clutter/clutter-private.h:
* clutter/clutter-main.[ch]: Add clutter_get_default_frame_rate()
and clutter_set_default_frame_rate(); these two functions control
the default frame rate to be used when creating timelines. Currently
is set to 60 frames-per-second.

ChangeLog
clutter/clutter-main.c
clutter/clutter-main.h
clutter/clutter-private.h
clutter/clutter-timeline.c
clutter/clutter-timeline.h

index 7986be5..31bcd1b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,19 @@
+2007-10-16  Emmanuele Bassi  <ebassi@openedhand.com>
+
+       * clutter/clutter-timeline.[ch]: Added ClutterTimeline:duration,
+       a property for setting the duration of a timeline in milliseconds.
+       The property comes with accessors and a new constructor. The
+       frame rate used is the default value.
+
+       * clutter/clutter-private.h:
+       * clutter/clutter-main.[ch]: Add clutter_get_default_frame_rate()
+       and clutter_set_default_frame_rate(); these two functions control
+       the default frame rate to be used when creating timelines. Currently
+       is set to 60 frames-per-second.
+
 2007-10-16  Tomas Frydrych  <tf@o-hand.com>
 
-       * build/msvc_2k5
+       * build/msvc_2k5:
        Added MSVC project files.
 
 2007-10-16  Emmanuele bassi  <ebassi@openedhand.com>
index 47c69ac..0ce8dbe 100644 (file)
@@ -650,7 +650,7 @@ clutter_get_debug_enabled (void)
 #endif
 }
 
-ClutterMainContext*
+ClutterMainContext *
 clutter_context_get_default (void)
 {
   if (G_UNLIKELY(!ClutterCntx))
@@ -760,6 +760,8 @@ pre_parse_hook (GOptionContext  *context,
   clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
   pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0);
 
+  clutter_context->frame_rate = 60;
+
   clutter_context->actor_hash = g_hash_table_new (NULL, NULL);
 
   backend = clutter_context->backend;
@@ -777,7 +779,6 @@ pre_parse_hook (GOptionContext  *context,
     }
 #endif /* CLUTTER_ENABLE_DEBUG */
 
-
   env_string = g_getenv ("CLUTTER_SHOW_FPS");
   if (env_string)
     clutter_show_fps = TRUE;
@@ -1133,8 +1134,9 @@ event_click_count_generate (ClutterEvent *event)
     }
 }
 
-static void 
-deliver_event (ClutterEvent *event, ClutterActor *source)
+static inline void 
+deliver_event (ClutterEvent *event,
+               ClutterActor *source)
 {
 #define MAX_EVENT_DEPTH 512
 
@@ -1150,8 +1152,8 @@ deliver_event (ClutterEvent *event, ClutterActor *source)
   lock = TRUE; /* Guard against reentrancy */
 
   /* Sorry Mr Bassi. */
-  if (event_tree == NULL)
-    event_tree = g_new0(ClutterActor*, MAX_EVENT_DEPTH);
+  if (G_UNLIKELY (event_tree == NULL))
+    event_tree = g_new0 (ClutterActor *, MAX_EVENT_DEPTH);
 
   actor = source;
 
@@ -1166,21 +1168,23 @@ deliver_event (ClutterEvent *event, ClutterActor *source)
     }
 
   /* Capture */
-  for (i=n_tree_events-1; i >= 0; i--)
-      if (clutter_actor_event (event_tree[i], event, TRUE))
-       goto done;
+  for (i = n_tree_events-1; i >= 0; i--)
+    if (clutter_actor_event (event_tree[i], event, TRUE))
+      goto done;
 
   /* Bubble */
-  for (i=0; i < n_tree_events; i++)
+  for (i = 0; i < n_tree_events; i++)
     if (clutter_actor_event (event_tree[i], event, FALSE))
       goto done;
 
- done:
+done:
 
-  for (i=0; i < n_tree_events; i++)
+  for (i = 0; i < n_tree_events; i++)
     g_object_unref (event_tree[i]);
 
   lock = FALSE;
+
+#undef MAX_EVENT_DEPTH
 }
 
 /** 
@@ -1239,7 +1243,7 @@ clutter_do_event (ClutterEvent *event)
       {
        ClutterActor *actor = NULL;
 
-       actor = clutter_stage_get_key_focus (CLUTTER_STAGE(stage));
+       actor = clutter_stage_get_key_focus (CLUTTER_STAGE (stage));
 
        g_return_if_fail (actor != NULL);
 
@@ -1276,6 +1280,8 @@ clutter_do_event (ClutterEvent *event)
        actor = _clutter_do_pick (CLUTTER_STAGE (stage), 
                                  x, y, 
                                  CLUTTER_PICK_REACTIVE);
+        if (!actor)
+          break;
 
         /* FIXME: for an optimisation should check if there are
         * actually any reactive actors and avoid the pick all togeather
@@ -1285,8 +1291,6 @@ clutter_do_event (ClutterEvent *event)
        CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p", 
                      x, y, actor);
 
-       g_return_if_fail (actor != NULL);
-
        if (event->type == CLUTTER_SCROLL)
          event->scroll.source = actor;
        else
@@ -1382,3 +1386,23 @@ clutter_base_init (void)
     }
 }
 
+guint
+clutter_get_default_frame_rate (void)
+{
+  ClutterMainContext *context;
+
+  context = clutter_context_get_default ();
+  
+  return context->frame_rate;
+}
+
+void
+clutter_set_default_frame_rate (guint frames_per_sec)
+{
+  ClutterMainContext *context;
+
+  context = clutter_context_get_default ();
+
+  if (context->frame_rate != frames_per_sec)
+    context->frame_rate = frames_per_sec;
+}
index d4e985e..0ebe649 100644 (file)
@@ -100,10 +100,11 @@ guint            clutter_threads_add_timeout_full   (gint           priority,
                                                      gpointer       data,
                                                      GDestroyNotify notify);
 
-void             clutter_enable_motion_events (gboolean enable);
-
-gboolean         clutter_get_motion_events_enabled (void);
+void             clutter_enable_motion_events       (gboolean enable);
+gboolean         clutter_get_motion_events_enabled  (void);
 
+guint            clutter_get_default_frame_rate     (void);
+void             clutter_set_default_frame_rate     (guint frames_per_sec);
 
 G_END_DECLS
 
index f2fda45..2de3a87 100644 (file)
@@ -83,6 +83,8 @@ struct _ClutterMainContext
   gint             num_reactives;      /* Num of reactive actors */
 
   GHashTable      *actor_hash;        /* Hash of all actors mapped to id */
+
+  guint            frame_rate;         /* Default FPS */
 };
 
 #define CLUTTER_CONTEXT()      (clutter_context_get_default ())
index adc9ed2..51a25d2 100644 (file)
@@ -64,6 +64,7 @@ struct _ClutterTimelinePrivate
   guint n_frames;
   guint current_frame_num;
   guint delay;
+  guint duration;
 
   gulong last_frame_msecs;
   gulong start_frame_secs;
@@ -78,7 +79,8 @@ enum
   PROP_FPS,
   PROP_NUM_FRAMES,
   PROP_LOOP,
-  PROP_DELAY
+  PROP_DELAY,
+  PROP_DURATION
 };
 
 enum
@@ -124,7 +126,7 @@ timeout_add (guint          interval,
 {
   guint res;
 
-  if (timeline_use_pool)
+  if (G_LIKELY (timeline_use_pool))
     {
       g_assert (timeline_pool != NULL);
       res = clutter_timeout_pool_add (timeline_pool,
@@ -144,7 +146,7 @@ timeout_add (guint          interval,
 static void
 timeout_remove (guint tag)
 {
-  if (timeline_use_pool)
+  if (G_LIKELY (timeline_use_pool))
     {
       g_assert (timeline_pool != NULL);
       clutter_timeout_pool_remove (timeline_pool, tag);
@@ -181,6 +183,9 @@ clutter_timeline_set_property (GObject      *object,
     case PROP_DELAY:
       priv->delay = g_value_get_uint (value);
       break;
+    case PROP_DURATION:
+      clutter_timeline_set_duration (timeline, g_value_get_uint (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -213,6 +218,9 @@ clutter_timeline_get_property (GObject    *object,
     case PROP_DELAY:
       g_value_set_uint (value, priv->delay);
       break;
+    case PROP_DURATION:
+      g_value_set_uint (value, priv->duration);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -274,8 +282,8 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
                                                       "Frames Per Second",
                                                       "Timeline frames per second",
                                                       1, 1000,
-                                                      50,
-                                                      G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
+                                                      60,
+                                                      CLUTTER_PARAM_READWRITE));
   /**
    * ClutterTimeline:num-frames:
    *
@@ -288,7 +296,7 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
                                                       "Timelines total number of frames",
                                                       1, G_MAXUINT,
                                                       1,
-                                                      G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
+                                                      CLUTTER_PARAM_READWRITE));
   /**
    * ClutterTimeline:loop:
    *
@@ -300,7 +308,7 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
                                                          "Loop",
                                                          "Should the timeline automatically restart",
                                                          FALSE,
-                                                         G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
+                                                         CLUTTER_PARAM_READWRITE));
   /**
    * ClutterTimeline:delay:
    *
@@ -316,7 +324,23 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
                                                       "Delay before start",
                                                       0, G_MAXUINT,
                                                       0,
-                                                      G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
+                                                      CLUTTER_PARAM_READWRITE));
+  /**
+   * ClutterTimeline:duration:
+   *
+   * Duration of the timeline in milliseconds, depending on the
+   * ClutterTimeline:fps value.
+   *
+   * Since: 0.6
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_DURATION,
+                                   g_param_spec_uint ("duration",
+                                                      "Duration",
+                                                      "Duration of the timeline in milliseconds",
+                                                      0, G_MAXUINT,
+                                                      1000,
+                                                      CLUTTER_PARAM_READWRITE));
 
   /**
    * ClutterTimeline::new-frame:
@@ -389,6 +413,9 @@ clutter_timeline_init (ClutterTimeline *self)
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
                                            CLUTTER_TYPE_TIMELINE,
                                            ClutterTimelinePrivate);
+
+  self->priv->fps = clutter_get_default_frame_rate ();
+  self->priv->n_frames = 0;
 }
 
 static gboolean
@@ -562,6 +589,9 @@ clutter_timeline_start (ClutterTimeline *timeline)
   if (priv->delay_id || priv->timeout_id)
     return;
 
+  if (priv->n_frames == 0)
+    return;
+
   if (priv->delay)
     {
       priv->delay_id = timeout_add (priv->delay,
@@ -881,6 +911,26 @@ clutter_timeline_clone (ClutterTimeline *timeline)
 }
 
 /**
+ * clutter_timeline_new_for_duration:
+ * @msecs: Duration of the timeline in milliseconds
+ *
+ * Creates a new #ClutterTimeline with a duration of @msecs using
+ * the value of the ClutterTimeline:fps property to compute the
+ * equivalent number of frames.
+ *
+ * Return value: the newly created #ClutterTimeline
+ *
+ * Since: 0.6
+ */
+ClutterTimeline *
+clutter_timeline_new_for_duration (guint msecs)
+{
+  return g_object_new (CLUTTER_TYPE_TIMELINE,
+                       "duration", msecs,
+                       NULL);
+}
+
+/**
  * clutter_timeline_new:
  * @n_frames: the number of frames
  * @fps: the number of frames per second
@@ -946,3 +996,102 @@ clutter_timeline_set_delay (ClutterTimeline *timeline,
       g_object_notify (G_OBJECT (timeline), "delay");
     }
 }
+
+/**
+ * clutter_timeline_get_duration:
+ * @timeline: a #ClutterTimeline
+ *
+ * Retrieves the duration of a #ClutterTimeline in milliseconds.
+ * See clutter_timeline_set_duration().
+ *
+ * Return value: the duration of the timeline, in milliseconds.
+ *
+ * Since: 0.6
+ */
+guint
+clutter_timeline_get_duration (ClutterTimeline *timeline)
+{
+  g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0);
+
+  return timeline->priv->duration;
+}
+
+/**
+ * clutter_timeline_set_duration:
+ * @timeline: a #ClutterTimeline
+ * @msecs: duration of the timeline in milliseconds
+ *
+ * Sets the duration of the timeline, in milliseconds. The speed
+ * of the timeline depends on the ClutterTimeline:fps setting.
+ *
+ * Since: 0.6
+ */
+void
+clutter_timeline_set_duration (ClutterTimeline *timeline,
+                               guint            msecs)
+{
+  ClutterTimelinePrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
+
+  priv = timeline->priv;
+
+  if (priv->duration != msecs)
+    {
+      g_object_ref (timeline);
+
+      g_object_freeze_notify (G_OBJECT (timeline));
+
+      priv->duration = msecs;
+
+      priv->n_frames = priv->duration / 1000
+                       * priv->fps;
+
+      g_object_notify (G_OBJECT (timeline), "num-frames");
+      g_object_notify (G_OBJECT (timeline), "duration");
+
+      g_object_thaw_notify (G_OBJECT (timeline));
+      g_object_unref (timeline);
+    }
+}
+
+/**
+ * clutter_timeline_get_progress:
+ * @timeline: a #ClutterTimeline
+ *
+ * The position of the timeline in a [0, 1] interval.
+ *
+ * Return value: the position of the timeline.
+ *
+ * Since: 0.6
+ */
+gdouble
+clutter_timeline_get_progress (ClutterTimeline *timeline)
+{
+  g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0.);
+
+  return CLUTTER_FIXED_TO_DOUBLE (clutter_timeline_get_progressx (timeline));
+}
+
+/**
+ * clutter_timeline_get_progressx:
+ * @timeline: a #ClutterTimeline
+ *
+ * Fixed point version of clutter_timeline_get_progress().
+ *
+ * Return value: the position of the timeline as a fixed point value
+ *
+ * Since: 0.6
+ */
+ClutterFixed
+clutter_timeline_get_progressx (ClutterTimeline *timeline)
+{
+  ClutterTimelinePrivate *priv;
+
+  g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0);
+
+  priv = timeline->priv;
+
+  return CLUTTER_FIXED_DIV (CLUTTER_INT_TO_FIXED (priv->current_frame_num),
+                            CLUTTER_INT_TO_FIXED (priv->n_frames));
+}
index 2932a9d..42fd6e0 100644 (file)
@@ -29,6 +29,7 @@
 /* clutter-timeline.h */
 
 #include <glib-object.h>
+#include <clutter/clutter-fixed.h>
 
 G_BEGIN_DECLS
 
@@ -90,8 +91,12 @@ GType clutter_timeline_get_type (void) G_GNUC_CONST;
 
 ClutterTimeline *clutter_timeline_new               (guint            n_frames,
                                                      guint            fps);
+ClutterTimeline *clutter_timeline_new_for_duration  (guint            msecs);
 ClutterTimeline *clutter_timeline_clone             (ClutterTimeline *timeline);
 
+guint            clutter_timeline_get_duration      (ClutterTimeline *timeline);
+void             clutter_timeline_set_duration      (ClutterTimeline *timeline,
+                                                     guint            msecs);
 guint            clutter_timeline_get_speed         (ClutterTimeline *timeline);
 void             clutter_timeline_set_speed         (ClutterTimeline *timeline,
                                                      guint            fps);
@@ -107,6 +112,8 @@ void             clutter_timeline_skip              (ClutterTimeline *timeline,
 void             clutter_timeline_advance           (ClutterTimeline *timeline,
                                                      guint            frame_num);
 gint             clutter_timeline_get_current_frame (ClutterTimeline *timeline);
+gdouble          clutter_timeline_get_progress      (ClutterTimeline *timeline);
+ClutterFixed     clutter_timeline_get_progressx     (ClutterTimeline *timeline);
 void             clutter_timeline_set_n_frames      (ClutterTimeline *timeline,
                                                      guint            n_frames);
 guint            clutter_timeline_get_n_frames      (ClutterTimeline *timeline);