From 9c7afe0c5bf99e38c6fd4584b8fa3b0ed02cf996 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 13:05:12 +0100 Subject: [PATCH] [timeline] Remove the concept of frames from timelines Timelines no longer work in terms of a frame rate and a number of frames but instead just have a duration in milliseconds. This better matches the working of the master clock where if any timelines are running it will redraw as fast as possible rather than limiting to the lowest rated timeline. Most applications will just create animations and expect them to finish in a certain amount of time without caring about how many frames are drawn. If a frame is going to be drawn it might as well update all of the animations to some fraction of the total animation rather than rounding to the nearest whole frame. The 'frame_num' parameter of the new-frame signal is now 'msecs' which is a number of milliseconds progressed along the timeline. Applications should use clutter_timeline_get_progress instead of the frame number. Markers can now only be attached at a time value. The position is stored in milliseconds rather than at a frame number. test-timeline-smoothness and test-timeline-dup-frames have been removed because they no longer make sense. --- clutter/clutter-alpha.c | 116 ++-- clutter/clutter-timeline.c | 640 ++++++-------------- clutter/clutter-timeline.h | 24 +- doc/reference/clutter/clutter-sections.txt | 8 +- tests/conform/Makefile.am | 2 - tests/conform/test-conform-main.c | 3 - tests/conform/test-timeline-dup-frames.c | 134 ---- tests/conform/test-timeline-interpolate.c | 19 +- tests/conform/test-timeline-rewind.c | 12 +- tests/conform/test-timeline-smoothness.c | 147 ----- tests/conform/test-timeline.c | 48 +- tests/interactive/test-actor-clone.c | 7 +- tests/interactive/test-actors.c | 9 +- tests/interactive/test-behave.c | 2 +- tests/interactive/test-cogl-multitexture.c | 8 +- tests/interactive/test-cogl-primitives.c | 7 +- tests/interactive/test-cogl-tex-polygon.c | 2 +- tests/interactive/test-cogl-tex-tile.c | 2 +- tests/interactive/test-cogl-vertex-buffer.c | 5 +- tests/interactive/test-depth.c | 2 +- tests/interactive/test-layout.c | 2 +- tests/interactive/test-multistage.c | 2 +- tests/interactive/test-paint-wrapper.c | 13 +- tests/interactive/test-pixmap.c | 2 +- tests/interactive/test-rotate.c | 2 +- tests/interactive/test-scale.c | 2 +- tests/interactive/test-score.c | 10 +- tests/interactive/test-texture-async.c | 2 +- tests/interactive/test-texture-quality.c | 2 +- tests/interactive/test-threads.c | 2 +- tests/interactive/test-viewport.c | 2 +- 31 files changed, 324 insertions(+), 914 deletions(-) delete mode 100644 tests/conform/test-timeline-dup-frames.c delete mode 100644 tests/conform/test-timeline-smoothness.c diff --git a/clutter/clutter-alpha.c b/clutter/clutter-alpha.c index a38a03f73..57b057aa1 100644 --- a/clutter/clutter-alpha.c +++ b/clutter/clutter-alpha.c @@ -603,9 +603,7 @@ clutter_ease_out_quad (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return -1.0 * p * (p - 2); } @@ -615,8 +613,8 @@ clutter_ease_in_out_quad (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); if (p < 1) @@ -632,9 +630,7 @@ clutter_ease_in_cubic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return p * p * p; } @@ -644,8 +640,8 @@ clutter_ease_out_cubic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / d - 1; return p * p * p + 1; @@ -656,8 +652,8 @@ clutter_ease_in_out_cubic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); if (p < 1) @@ -673,9 +669,7 @@ clutter_ease_in_quart (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return p * p * p * p; } @@ -685,8 +679,8 @@ clutter_ease_out_quart (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / d - 1; return -1.0 * (p * p * p * p - 1); @@ -697,8 +691,8 @@ clutter_ease_in_out_quart (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); if (p < 1) @@ -714,9 +708,7 @@ clutter_ease_in_quint (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return p * p * p * p * p; } @@ -726,8 +718,8 @@ clutter_ease_out_quint (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / d - 1; return p * p * p * p * p + 1; @@ -738,8 +730,8 @@ clutter_ease_in_out_quint (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); if (p < 1) @@ -755,8 +747,8 @@ clutter_ease_in_sine (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return -1.0 * cos (t / d * G_PI_2) + 1.0; } @@ -766,8 +758,8 @@ clutter_ease_out_sine (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return sin (t / d * G_PI_2); } @@ -777,8 +769,8 @@ clutter_ease_in_out_sine (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return -0.5 * (cos (G_PI * t / d) - 1); } @@ -788,8 +780,8 @@ clutter_ease_in_expo (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1)); } @@ -799,8 +791,8 @@ clutter_ease_out_expo (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1; } @@ -810,8 +802,8 @@ clutter_ease_in_out_expo (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p; if (t == 0) @@ -835,9 +827,7 @@ clutter_ease_in_circ (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return -1.0 * (sqrt (1 - p * p) - 1); } @@ -847,8 +837,8 @@ clutter_ease_out_circ (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / d - 1; return sqrt (1 - p * p); @@ -859,8 +849,8 @@ clutter_ease_in_out_circ (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); if (p < 1) @@ -876,8 +866,8 @@ clutter_ease_in_elastic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = d * .3; gdouble s = p / 4; gdouble q = t / d; @@ -895,8 +885,8 @@ clutter_ease_out_elastic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = d * .3; gdouble s = p / 4; gdouble q = t / d; @@ -912,8 +902,8 @@ clutter_ease_in_out_elastic (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = d * (.3 * 1.5); gdouble s = p / 4; gdouble q = t / (d / 2); @@ -942,9 +932,7 @@ clutter_ease_in_back (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); - gdouble p = t / d; + gdouble p = clutter_timeline_get_progress (timeline); return p * p * ((1.70158 + 1) * p - 1.70158); } @@ -954,8 +942,8 @@ clutter_ease_out_back (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / d - 1; return p * p * ((1.70158 + 1) * p + 1.70158) + 1; @@ -966,8 +954,8 @@ clutter_ease_in_out_back (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); gdouble p = t / (d / 2); gdouble s = 1.70158 * 1.525; @@ -1019,8 +1007,8 @@ clutter_ease_in_bounce (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return ease_in_bounce_internal (t, d); } @@ -1030,8 +1018,8 @@ clutter_ease_out_bounce (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); return ease_out_bounce_internal (t, d); } @@ -1041,8 +1029,8 @@ clutter_ease_in_out_bounce (ClutterAlpha *alpha, gpointer dummy G_GNUC_UNUSED) { ClutterTimeline *timeline = alpha->priv->timeline; - gdouble t = clutter_timeline_get_current_frame (timeline); - gdouble d = clutter_timeline_get_n_frames (timeline); + gdouble t = clutter_timeline_get_elapsed_time (timeline); + gdouble d = clutter_timeline_get_duration (timeline); if (t < d / 2) return ease_in_bounce_internal (t * 2, d) * 0.5; diff --git a/clutter/clutter-timeline.c b/clutter/clutter-timeline.c index 761c5e1c5..d74a10786 100644 --- a/clutter/clutter-timeline.c +++ b/clutter/clutter-timeline.c @@ -99,18 +99,15 @@ struct _ClutterTimelinePrivate guint delay_id; - gint current_frame_num; - - guint fps; - guint n_frames; + /* The total length in milliseconds of this timeline */ + guint duration; guint delay; - gint skipped_frames; + /* The current amount of elapsed time */ + gint elapsed_time; + /* The elapsed time since the last frame was fired */ + gint msecs_delta; - guint msecs_delta; - guint frame_interval; - - GHashTable *markers_by_frame; GHashTable *markers_by_name; guint loop : 1; @@ -119,7 +116,7 @@ struct _ClutterTimelinePrivate typedef struct { gchar *name; - guint frame_num; + guint msecs; GQuark quark; } TimelineMarker; @@ -127,8 +124,6 @@ enum { PROP_0, - PROP_FPS, - PROP_NUM_FRAMES, PROP_LOOP, PROP_DELAY, PROP_DURATION, @@ -150,13 +145,13 @@ static guint timeline_signals[LAST_SIGNAL] = { 0, }; static TimelineMarker * timeline_marker_new (const gchar *name, - guint frame_num) + guint msecs) { TimelineMarker *marker = g_slice_new0 (TimelineMarker); marker->name = g_strdup (name); marker->quark = g_quark_from_string (marker->name); - marker->frame_num = frame_num; + marker->msecs = msecs; return marker; } @@ -189,14 +184,6 @@ clutter_timeline_set_property (GObject *object, switch (prop_id) { - case PROP_FPS: - clutter_timeline_set_speed (timeline, g_value_get_uint (value)); - break; - - case PROP_NUM_FRAMES: - clutter_timeline_set_n_frames (timeline, g_value_get_uint (value)); - break; - case PROP_LOOP: priv->loop = g_value_get_boolean (value); break; @@ -233,14 +220,6 @@ clutter_timeline_get_property (GObject *object, switch (prop_id) { - case PROP_FPS: - g_value_set_uint (value, priv->fps); - break; - - case PROP_NUM_FRAMES: - g_value_set_uint (value, priv->n_frames); - break; - case PROP_LOOP: g_value_set_boolean (value, priv->loop); break; @@ -270,9 +249,6 @@ clutter_timeline_finalize (GObject *object) ClutterTimelinePrivate *priv = self->priv; ClutterMasterClock *master_clock; - if (priv->markers_by_frame) - g_hash_table_destroy (priv->markers_by_frame); - if (priv->markers_by_name) g_hash_table_destroy (priv->markers_by_name); @@ -312,36 +288,6 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) g_type_class_add_private (klass, sizeof (ClutterTimelinePrivate)); - /** - * ClutterTimeline:fps: - * - * Number of frames per second. Because of the nature of the main - * loop used by Clutter, we can only accept a granularity of one - * frame per millisecond. - * - * This value is to be considered a best approximation. - */ - pspec = g_param_spec_uint ("fps", - "Frames Per Second", - "Frames per second", - 1, 1000, - 60, - CLUTTER_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_FPS, pspec); - - /** - * ClutterTimeline:num-frames: - * - * Total number of frames for the timeline. - */ - pspec = g_param_spec_uint ("num-frames", - "Total number of frames", - "Total number of frames", - 1, G_MAXUINT, - 1, - CLUTTER_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_NUM_FRAMES, pspec); - /** * ClutterTimeline:loop: * @@ -405,11 +351,11 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) /** * ClutterTimeline::new-frame: * @timeline: the timeline which received the signal - * @frame_num: the number of the new frame between 0 and - * ClutterTimeline:num-frames + * @msecs: the elapsed time between 0 and duration * - * The ::new-frame signal is emitted each time a new frame in the - * timeline is reached. + * The ::new-frame signal is emitted for each timeline running + * timeline before a new frame is drawn to give animations a chance + * to update the scene. */ timeline_signals[NEW_FRAME] = g_signal_new (I_("new-frame"), @@ -470,18 +416,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass) * ClutterTimeline::marker-reached: * @timeline: the #ClutterTimeline which received the signal * @marker_name: the name of the marker reached - * @frame_num: the frame number + * @msecs: the elapsed time * * The ::marker-reached signal is emitted each time a timeline - * reaches a marker set with clutter_timeline_add_marker_at_frame() - * or clutter_timeline_add_marker_at_time(). This signal is - * detailed with the name of the marker as well, so it is - * possible to connect a callback to the ::marker-reached signal - * for a specific marker with: + * reaches a marker set with + * clutter_timeline_add_marker_at_time(). This signal is detailed + * with the name of the marker as well, so it is possible to connect + * a callback to the ::marker-reached signal for a specific marker + * with: * * - * clutter_timeline_add_marker_at_frame (timeline, "foo", 24); - * clutter_timeline_add_marker_at_frame (timeline, "bar", 48); + * clutter_timeline_add_marker_at_time (timeline, "foo", 500); + * clutter_timeline_add_marker_at_time (timeline, "bar", 750); * * g_signal_connect (timeline, "marker-reached", * G_CALLBACK (each_marker_reached), NULL); @@ -520,50 +466,51 @@ clutter_timeline_init (ClutterTimeline *self) G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_TIMELINE, ClutterTimelinePrivate); - priv->fps = clutter_get_default_frame_rate (); - priv->frame_interval = 1000 / priv->fps; - priv->n_frames = 0; - priv->msecs_delta = 0; + priv->duration = 0; + priv->delay = 0; + priv->elapsed_time = 0; master_clock = _clutter_master_clock_get_default (); _clutter_master_clock_add_timeline (master_clock, self); } +static void +check_if_marker_hit (const gchar *name, + TimelineMarker *marker, + ClutterTimeline *timeline) +{ + ClutterTimelinePrivate *priv = timeline->priv; + + if (priv->direction == CLUTTER_TIMELINE_FORWARD + ? (marker->msecs > priv->elapsed_time - priv->msecs_delta + && marker->msecs <= priv->elapsed_time) + : (marker->msecs >= priv->elapsed_time + && marker->msecs < priv->elapsed_time + priv->msecs_delta)) + { + CLUTTER_NOTE (SCHEDULER, "Marker '%s' reached", name); + + g_signal_emit (timeline, timeline_signals[MARKER_REACHED], + marker->quark, + name, + marker->msecs); + } +} + static void emit_frame_signal (ClutterTimeline *timeline) { ClutterTimelinePrivate *priv = timeline->priv; - gint i; g_signal_emit (timeline, timeline_signals[NEW_FRAME], 0, - priv->current_frame_num); + priv->elapsed_time); /* shortcircuit here if we don't have any marker installed */ - if (priv->markers_by_name == NULL || - priv->markers_by_frame == NULL) + if (priv->markers_by_name == NULL) return; - for (i = priv->skipped_frames; i >= 0; i--) - { - gint frame_num; - GSList *markers, *l; - - frame_num = priv->current_frame_num - + (priv->direction == CLUTTER_TIMELINE_FORWARD ? -i : i); - markers = g_hash_table_lookup (priv->markers_by_frame, - GUINT_TO_POINTER (frame_num)); - for (l = markers; l; l = l->next) - { - TimelineMarker *marker = l->data; - - CLUTTER_NOTE (SCHEDULER, "Marker '%s' reached", marker->name); - - g_signal_emit (timeline, timeline_signals[MARKER_REACHED], - marker->quark, - marker->name, - marker->frame_num); - } - } + g_hash_table_foreach (priv->markers_by_name, + (GHFunc) check_if_marker_hit, + timeline); } static gboolean @@ -571,17 +518,15 @@ is_complete (ClutterTimeline *timeline) { ClutterTimelinePrivate *priv = timeline->priv; - return ((priv->direction == CLUTTER_TIMELINE_FORWARD) && - (priv->current_frame_num >= priv->n_frames)) || - ((priv->direction == CLUTTER_TIMELINE_BACKWARD) && - (priv->current_frame_num <= 0)); + return (priv->direction == CLUTTER_TIMELINE_FORWARD + ? priv->elapsed_time >= priv->duration + : priv->elapsed_time <= 0); } static gboolean clutter_timeline_advance_internal (ClutterTimeline *timeline) { ClutterTimelinePrivate *priv; - guint n_frames, speed; priv = timeline->priv; @@ -589,28 +534,13 @@ clutter_timeline_advance_internal (ClutterTimeline *timeline) CLUTTER_TIMESTAMP (SCHEDULER, "Timeline [%p] activated (cur: %d)\n", timeline, - priv->current_frame_num); + priv->elapsed_time); - /* we need to avoid fps > 1000 */ - speed = MAX (1000 / priv->fps, 1); - - n_frames = priv->msecs_delta / speed; - if (n_frames == 0) - n_frames = 1; - - priv->skipped_frames = n_frames - 1; - - if (priv->skipped_frames) - CLUTTER_TIMESTAMP (SCHEDULER, - "Timeline [%p], skipping %d frames\n", - timeline, - priv->skipped_frames); - - /* Advance frames */ + /* Advance time */ if (priv->direction == CLUTTER_TIMELINE_FORWARD) - priv->current_frame_num += n_frames; + priv->elapsed_time += priv->msecs_delta; else - priv->current_frame_num -= n_frames; + priv->elapsed_time -= priv->msecs_delta; /* If we have not reached the end of the timeline: */ if (!is_complete (timeline)) @@ -632,30 +562,23 @@ clutter_timeline_advance_internal (ClutterTimeline *timeline) { /* Handle loop or stop */ ClutterTimelineDirection saved_direction = priv->direction; - guint overflow_frame_num = priv->current_frame_num; - gint end_frame; + guint overflow_msecs = priv->elapsed_time; + gint end_msecs; - /* Update the current frame number in case the signal handlers - want to take a peek. Don't count skipped frames that run past - the end of the timeline */ + /* Update the current elapsed time in case the signal handlers + want to take a peek. */ if (priv->direction == CLUTTER_TIMELINE_FORWARD) - { - priv->skipped_frames -= priv->current_frame_num - priv->n_frames; - priv->current_frame_num = priv->n_frames; - } + priv->elapsed_time = priv->duration; else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) - { - priv->skipped_frames += priv->current_frame_num; - priv->current_frame_num = 0; - } + priv->elapsed_time = 0; - end_frame = priv->current_frame_num; + end_msecs = priv->elapsed_time; /* Emit the signal */ emit_frame_signal (timeline); - /* Did the signal handler modify the current_frame_num */ - if (priv->current_frame_num != end_frame) + /* Did the signal handler modify the elapsed time? */ + if (priv->elapsed_time != end_msecs) { g_object_unref (timeline); return TRUE; @@ -665,11 +588,10 @@ clutter_timeline_advance_internal (ClutterTimeline *timeline) * on the last frame we will still go ahead and send the * completed signal */ CLUTTER_NOTE (SCHEDULER, - "Timeline [%p] completed (cur: %d, tot: %d, drop: %d)", + "Timeline [%p] completed (cur: %d, tot: %d)", timeline, - priv->current_frame_num, - priv->n_frames, - n_frames - 1); + priv->elapsed_time, + priv->msecs_delta); if (!priv->loop && priv->is_playing) { @@ -685,13 +607,13 @@ clutter_timeline_advance_internal (ClutterTimeline *timeline) g_signal_emit (timeline, timeline_signals[COMPLETED], 0); /* Again check to see if the user has manually played with - * current_frame_num, before we finally stop or loop the timeline */ + * the elapsed time, before we finally stop or loop the timeline */ - if (priv->current_frame_num != end_frame && - !(/* Except allow moving from frame 0 -> n_frame (or vice-versa) + if (priv->elapsed_time != end_msecs && + !(/* Except allow changing time from 0 -> duration (or vice-versa) since these are considered equivalent */ - (priv->current_frame_num == 0 && end_frame == priv->n_frames) || - (priv->current_frame_num == priv->n_frames && end_frame == 0) + (priv->elapsed_time == 0 && end_msecs == priv->duration) || + (priv->elapsed_time == priv->duration && end_msecs == 0) )) { g_object_unref (timeline); @@ -702,16 +624,13 @@ clutter_timeline_advance_internal (ClutterTimeline *timeline) { /* We try and interpolate smoothly around a loop */ if (saved_direction == CLUTTER_TIMELINE_FORWARD) - priv->current_frame_num = overflow_frame_num - priv->n_frames; + priv->elapsed_time = overflow_msecs - priv->duration; else - priv->current_frame_num = priv->n_frames + overflow_frame_num; + priv->elapsed_time = priv->duration + overflow_msecs; /* Or if the direction changed, we try and bounce */ if (priv->direction != saved_direction) - { - priv->current_frame_num = priv->n_frames - - priv->current_frame_num; - } + priv->elapsed_time = priv->duration - priv->elapsed_time; g_object_unref (timeline); return TRUE; @@ -759,7 +678,7 @@ clutter_timeline_start (ClutterTimeline *timeline) if (priv->delay_id || priv->is_playing) return; - if (priv->n_frames == 0) + if (priv->duration == 0) return; if (priv->delay) @@ -875,19 +794,19 @@ clutter_timeline_rewind (ClutterTimeline *timeline) if (priv->direction == CLUTTER_TIMELINE_FORWARD) clutter_timeline_advance (timeline, 0); else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) - clutter_timeline_advance (timeline, priv->n_frames); + clutter_timeline_advance (timeline, priv->duration); } /** * clutter_timeline_skip: * @timeline: A #ClutterTimeline - * @n_frames: Number of frames to skip + * @msecs: Amount of time to skip * - * Advance timeline by the requested number of frames. + * Advance timeline by the requested time in milliseconds */ void clutter_timeline_skip (ClutterTimeline *timeline, - guint n_frames) + guint msecs) { ClutterTimelinePrivate *priv; @@ -897,17 +816,17 @@ clutter_timeline_skip (ClutterTimeline *timeline, if (priv->direction == CLUTTER_TIMELINE_FORWARD) { - priv->current_frame_num += n_frames; + priv->elapsed_time += msecs; - if (priv->current_frame_num > priv->n_frames) - priv->current_frame_num = 1; + if (priv->elapsed_time > priv->duration) + priv->elapsed_time = 1; } else if (priv->direction == CLUTTER_TIMELINE_BACKWARD) { - priv->current_frame_num -= n_frames; + priv->elapsed_time -= msecs; - if (priv->current_frame_num < 1) - priv->current_frame_num = priv->n_frames - 1; + if (priv->elapsed_time < 1) + priv->elapsed_time = priv->duration - 1; } priv->msecs_delta = 0; @@ -916,18 +835,19 @@ clutter_timeline_skip (ClutterTimeline *timeline, /** * clutter_timeline_advance: * @timeline: A #ClutterTimeline - * @frame_num: Frame number to advance to + * @msecs: Time to advance to * - * Advance timeline to the requested frame number. + * Advance timeline to the requested point. The point is given as a + * time in milliseconds since the timeline started. * * The @timeline will not emit the #ClutterTimeline::new-frame - * signal for @frame_num. The first ::new-frame signal after the call to - * clutter_timeline_advance() will be emitted for a frame following - * @frame_num. + * signal for the given time. The first ::new-frame signal after the call to + * clutter_timeline_advance() will be emit the skipped markers. + * */ void clutter_timeline_advance (ClutterTimeline *timeline, - guint frame_num) + guint msecs) { ClutterTimelinePrivate *priv; @@ -935,123 +855,23 @@ clutter_timeline_advance (ClutterTimeline *timeline, priv = timeline->priv; - priv->current_frame_num = CLAMP (frame_num, 0, priv->n_frames); + priv->elapsed_time = CLAMP (msecs, 0, priv->duration); } /** - * clutter_timeline_get_current_frame: + * clutter_timeline_get_elapsed_time: * @timeline: A #ClutterTimeline * - * Request the current frame number of the timeline. + * Request the current time position of the timeline. * - * Return value: current frame number - */ -gint -clutter_timeline_get_current_frame (ClutterTimeline *timeline) -{ - g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); - - return timeline->priv->current_frame_num; -} - -/** - * clutter_timeline_get_n_frames: - * @timeline: A #ClutterTimeline - * - * Request the total number of frames for the #ClutterTimeline. - * - * Return value: the number of frames + * Return value: current elapsed time in milliseconds. */ guint -clutter_timeline_get_n_frames (ClutterTimeline *timeline) +clutter_timeline_get_elapsed_time (ClutterTimeline *timeline) { g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); - return timeline->priv->n_frames; -} - -/** - * clutter_timeline_set_n_frames: - * @timeline: a #ClutterTimeline - * @n_frames: the number of frames - * - * Sets the total number of frames for @timeline - */ -void -clutter_timeline_set_n_frames (ClutterTimeline *timeline, - guint n_frames) -{ - ClutterTimelinePrivate *priv; - - g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); - g_return_if_fail (n_frames > 0); - - priv = timeline->priv; - - if (priv->n_frames != n_frames) - { - g_object_freeze_notify (G_OBJECT (timeline)); - - priv->n_frames = n_frames; - - g_object_notify (G_OBJECT (timeline), "num-frames"); - g_object_notify (G_OBJECT (timeline), "duration"); - - g_object_thaw_notify (G_OBJECT (timeline)); - } -} - -/** - * clutter_timeline_set_speed: - * @timeline: A #ClutterTimeline - * @fps: New speed of timeline as frames per second, - * between 1 and 1000 - * - * Sets the speed of @timeline in frames per second. - */ -void -clutter_timeline_set_speed (ClutterTimeline *timeline, - guint fps) -{ - ClutterTimelinePrivate *priv; - - g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); - g_return_if_fail (fps > 0 && fps <= 1000); - - priv = timeline->priv; - - if (priv->fps != fps) - { - g_object_freeze_notify (G_OBJECT (timeline)); - - priv->fps = fps; - priv->frame_interval = 1000 / priv->fps; - - /* if the timeline is playing restart */ - if (priv->is_playing) - clutter_timeline_rewind (timeline); - - g_object_notify (G_OBJECT (timeline), "duration"); - g_object_notify (G_OBJECT (timeline), "fps"); - - g_object_thaw_notify (G_OBJECT (timeline)); - } -} - -/** - * clutter_timeline_get_speed: - * @timeline: a #ClutterTimeline - * - * Gets the frames per second played by @timeline - * - * Return value: the number of frames per second. - */ -guint -clutter_timeline_get_speed (ClutterTimeline *timeline) -{ - g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); - - return timeline->priv->fps; + return timeline->priv->elapsed_time; } /** @@ -1091,8 +911,7 @@ clutter_timeline_clone (ClutterTimeline *timeline) g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL); copy = g_object_new (CLUTTER_TYPE_TIMELINE, - "fps", clutter_timeline_get_speed (timeline), - "num-frames", clutter_timeline_get_n_frames (timeline), + "duration", clutter_timeline_get_duration (timeline), "loop", clutter_timeline_get_loop (timeline), "delay", clutter_timeline_get_delay (timeline), "direction", clutter_timeline_get_direction (timeline), @@ -1105,9 +924,7 @@ 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. + * Creates a new #ClutterTimeline with a duration of @msecs. * * Return value: the newly created #ClutterTimeline instance. Use * g_object_unref() when done using it @@ -1115,36 +932,13 @@ clutter_timeline_clone (ClutterTimeline *timeline) * Since: 0.6 */ ClutterTimeline * -clutter_timeline_new_for_duration (guint msecs) +clutter_timeline_new (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 - * - * Create a new #ClutterTimeline instance. - * - * Return Value: the newly created #ClutterTimeline instance. Use - * g_object_unref() when done using it - */ -ClutterTimeline* -clutter_timeline_new (guint n_frames, - guint fps) -{ - g_return_val_if_fail (n_frames > 0, NULL); - g_return_val_if_fail (fps > 0 && fps <= 1000, NULL); - - return g_object_new (CLUTTER_TYPE_TIMELINE, - "fps", fps, - "num-frames", n_frames, - NULL); -} - /** * clutter_timeline_get_delay: * @timeline: a #ClutterTimeline @@ -1209,7 +1003,7 @@ clutter_timeline_get_duration (ClutterTimeline *timeline) priv = timeline->priv; - return priv->n_frames * 1000 / priv->fps; + return priv->duration; } /** @@ -1227,18 +1021,18 @@ clutter_timeline_set_duration (ClutterTimeline *timeline, guint msecs) { ClutterTimelinePrivate *priv; - guint n_frames; g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + g_return_if_fail (msecs > 0); priv = timeline->priv; - n_frames = msecs * priv->fps / 1000; - if (n_frames < 1) - n_frames = 1; + if (priv->duration != msecs) + { + priv->duration = msecs; - /* this will notify :duration as well */ - clutter_timeline_set_n_frames (timeline, n_frames); + g_object_notify (G_OBJECT (timeline), "duration"); + } } /** @@ -1260,7 +1054,7 @@ clutter_timeline_get_progress (ClutterTimeline *timeline) priv = timeline->priv; - return (gdouble) priv->current_frame_num / (gdouble) priv->n_frames; + return (gdouble) priv->elapsed_time / (gdouble) priv->duration; } /** @@ -1323,8 +1117,8 @@ clutter_timeline_set_direction (ClutterTimeline *timeline, { priv->direction = direction; - if (priv->current_frame_num == 0) - priv->current_frame_num = priv->n_frames; + if (priv->elapsed_time == 0) + priv->elapsed_time = priv->duration; g_object_notify (G_OBJECT (timeline), "direction"); } @@ -1333,42 +1127,32 @@ clutter_timeline_set_direction (ClutterTimeline *timeline, /** * clutter_timeline_get_delta: * @timeline: a #ClutterTimeline - * @msecs: return location for the milliseconds elapsed since the last - * frame, or %NULL * - * Retrieves the number of frames and the amount of time elapsed since - * the last ClutterTimeline::new-frame signal. + * Retrieves the amount of time elapsed since the last + * ClutterTimeline::new-frame signal. * * This function is only useful inside handlers for the ::new-frame * signal, and its behaviour is undefined if the timeline is not * playing. * - * Return value: the amount of frames elapsed since the last one + * Return value: the amount of time in milliseconds elapsed since the + * last frame * * Since: 0.6 */ guint -clutter_timeline_get_delta (ClutterTimeline *timeline, - guint *msecs) +clutter_timeline_get_delta (ClutterTimeline *timeline) { ClutterTimelinePrivate *priv; g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); if (!clutter_timeline_is_playing (timeline)) - { - if (msecs) - *msecs = 0; - - return 0; - } + return 0; priv = timeline->priv; - if (msecs) - *msecs = timeline->priv->msecs_delta; - - return priv->skipped_frames + 1; + return timeline->priv->msecs_delta; } /* @@ -1392,95 +1176,36 @@ clutter_timeline_advance_delta (ClutterTimeline *timeline, priv = timeline->priv; - priv->msecs_delta += msecs; + priv->msecs_delta = msecs; - if (priv->msecs_delta < priv->frame_interval) - return; - else - { - clutter_timeline_advance_internal (timeline); - - /* Keep the remainder of the frame time so that it will be - counted towards the next time if the delta is short */ - priv->msecs_delta %= priv->frame_interval; - } + clutter_timeline_advance_internal (timeline); } static inline void clutter_timeline_add_marker_internal (ClutterTimeline *timeline, const gchar *marker_name, - guint frame_num) + guint msecs) { ClutterTimelinePrivate *priv = timeline->priv; TimelineMarker *marker; - GSList *markers; - /* create the hash tables that will hold the markers */ - if (G_UNLIKELY (priv->markers_by_name == NULL || - priv->markers_by_frame == NULL)) - { - priv->markers_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, - timeline_marker_free); - priv->markers_by_frame = g_hash_table_new (NULL, NULL); - } + /* create the hash table that will hold the markers */ + if (G_UNLIKELY (priv->markers_by_name == NULL)) + priv->markers_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, + timeline_marker_free); marker = g_hash_table_lookup (priv->markers_by_name, marker_name); if (G_UNLIKELY (marker)) { - g_warning ("A marker named '%s' already exists on frame %d", + g_warning ("A marker named '%s' already exists at time %d", marker->name, - marker->frame_num); + marker->msecs); return; } - marker = timeline_marker_new (marker_name, frame_num); + marker = timeline_marker_new (marker_name, msecs); g_hash_table_insert (priv->markers_by_name, marker->name, marker); - - markers = g_hash_table_lookup (priv->markers_by_frame, - GUINT_TO_POINTER (frame_num)); - if (!markers) - { - markers = g_slist_prepend (NULL, marker); - g_hash_table_insert (priv->markers_by_frame, - GUINT_TO_POINTER (frame_num), - markers); - } - else - { - markers = g_slist_prepend (markers, marker); - g_hash_table_replace (priv->markers_by_frame, - GUINT_TO_POINTER (frame_num), - markers); - } -} - -/** - * clutter_timeline_add_marker_at_frame: - * @timeline: a #ClutterTimeline - * @marker_name: the unique name for this marker - * @frame_num: the marker's frame - * - * Adds a named marker at @frame_num. Markers are unique string identifiers - * for a specific frame. Once @timeline reaches @frame_num, it will emit - * a ::marker-reached signal for each marker attached to that frame. - * - * A marker can be removed with clutter_timeline_remove_marker(). The - * timeline can be advanced to a marker using - * clutter_timeline_advance_to_marker(). - * - * Since: 0.8 - */ -void -clutter_timeline_add_marker_at_frame (ClutterTimeline *timeline, - const gchar *marker_name, - guint frame_num) -{ - g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); - g_return_if_fail (marker_name != NULL); - g_return_if_fail (frame_num <= clutter_timeline_get_n_frames (timeline)); - - clutter_timeline_add_marker_internal (timeline, marker_name, frame_num); } /** @@ -1489,9 +1214,15 @@ clutter_timeline_add_marker_at_frame (ClutterTimeline *timeline, * @marker_name: the unique name for this marker * @msecs: position of the marker in milliseconds * - * Time-based variant of clutter_timeline_add_marker_at_frame(). + * Adds a named marker that will be hit when the timeline has been + * running for @msecs milliseconds. Markers are unique string + * identifiers for a given time. Once @timeline reaches + * @msecs, it will emit a ::marker-reached signal for each marker + * attached to that time. * - * Adds a named marker at @msecs. + * A marker can be removed with clutter_timeline_remove_marker(). The + * timeline can be advanced to a marker using + * clutter_timeline_advance_to_marker(). * * Since: 0.8 */ @@ -1500,24 +1231,38 @@ clutter_timeline_add_marker_at_time (ClutterTimeline *timeline, const gchar *marker_name, guint msecs) { - guint frame_num; - g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); g_return_if_fail (marker_name != NULL); g_return_if_fail (msecs <= clutter_timeline_get_duration (timeline)); - frame_num = msecs * timeline->priv->fps / 1000; + clutter_timeline_add_marker_internal (timeline, marker_name, msecs); +} - clutter_timeline_add_marker_internal (timeline, marker_name, frame_num); +struct CollectMarkersClosure +{ + guint msecs; + GArray *markers; +}; + +static void +collect_markers (const gchar *key, + TimelineMarker *marker, + struct CollectMarkersClosure *data) +{ + if (marker->msecs == data->msecs) + { + gchar *name_copy = g_strdup (key); + g_array_append_val (data->markers, name_copy); + } } /** * clutter_timeline_list_markers: * @timeline: a #ClutterTimeline - * @frame_num: the frame number to check, or -1 + * @msecs: the time to check, or -1 * @n_markers: the number of markers returned * - * Retrieves the list of markers at @frame_num. If @frame_num is a + * Retrieves the list of markers at time @msecs. If @frame_num is a * negative integer, all the markers attached to @timeline will be * returned. * @@ -1529,7 +1274,7 @@ clutter_timeline_add_marker_at_time (ClutterTimeline *timeline, */ gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline, - gint frame_num, + gint msecs, gsize *n_markers) { ClutterTimelinePrivate *priv; @@ -1540,8 +1285,7 @@ clutter_timeline_list_markers (ClutterTimeline *timeline, priv = timeline->priv; - if (G_UNLIKELY (priv->markers_by_name == NULL || - priv->markers_by_frame == NULL)) + if (G_UNLIKELY (priv->markers_by_name == NULL)) { if (n_markers) *n_markers = 0; @@ -1549,7 +1293,7 @@ clutter_timeline_list_markers (ClutterTimeline *timeline, return NULL; } - if (frame_num < 0) + if (msecs < 0) { GList *markers, *l; @@ -1563,14 +1307,17 @@ clutter_timeline_list_markers (ClutterTimeline *timeline, } else { - GSList *markers, *l; + struct CollectMarkersClosure data; - markers = g_hash_table_lookup (priv->markers_by_frame, - GUINT_TO_POINTER (frame_num)); - retval = g_new0 (gchar*, g_slist_length (markers) + 1); + data.msecs = msecs; + data.markers = g_array_new (TRUE, FALSE, sizeof (gchar *)); - for (i = 0, l = markers; l != NULL; i++, l = l->next) - retval[i] = g_strdup (((TimelineMarker *) l->data)->name); + g_hash_table_foreach (priv->markers_by_name, + (GHFunc) collect_markers, + &data); + + i = data.markers->len; + retval = (gchar **) g_array_free (data.markers, FALSE); } if (n_markers) @@ -1584,10 +1331,10 @@ clutter_timeline_list_markers (ClutterTimeline *timeline, * @timeline: a #ClutterTimeline * @marker_name: the name of the marker * - * Advances @timeline to the frame of the given @marker_name. + * Advances @timeline to the time of the given @marker_name. * * Like clutter_timeline_advance(), this function will not - * emit the #ClutterTimeline::new-frame for the frame where @marker_name + * emit the #ClutterTimeline::new-frame for the time where @marker_name * is set, nor it will emit #ClutterTimeline::marker-reached for * @marker_name. * @@ -1605,8 +1352,7 @@ clutter_timeline_advance_to_marker (ClutterTimeline *timeline, priv = timeline->priv; - if (G_UNLIKELY (priv->markers_by_name == NULL || - priv->markers_by_frame == NULL)) + if (G_UNLIKELY (priv->markers_by_name == NULL)) { g_warning ("No marker named '%s' found.", marker_name); return; @@ -1619,7 +1365,7 @@ clutter_timeline_advance_to_marker (ClutterTimeline *timeline, return; } - clutter_timeline_advance (timeline, marker->frame_num); + clutter_timeline_advance (timeline, marker->msecs); } /** @@ -1637,15 +1383,13 @@ clutter_timeline_remove_marker (ClutterTimeline *timeline, { ClutterTimelinePrivate *priv; TimelineMarker *marker; - GSList *markers; g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); g_return_if_fail (marker_name != NULL); priv = timeline->priv; - if (G_UNLIKELY (priv->markers_by_name == NULL || - priv->markers_by_frame == NULL)) + if (G_UNLIKELY (priv->markers_by_name == NULL)) { g_warning ("No marker named '%s' found.", marker_name); return; @@ -1658,31 +1402,6 @@ clutter_timeline_remove_marker (ClutterTimeline *timeline, return; } - /* remove from the list of markers at the same frame */ - markers = g_hash_table_lookup (priv->markers_by_frame, - GUINT_TO_POINTER (marker->frame_num)); - if (G_LIKELY (markers)) - { - markers = g_slist_remove (markers, marker); - if (!markers) - { - /* no markers left, remove the slot */ - g_hash_table_remove (priv->markers_by_frame, - GUINT_TO_POINTER (marker->frame_num)); - } - else - g_hash_table_replace (priv->markers_by_frame, - GUINT_TO_POINTER (marker->frame_num), - markers); - } - else - { - /* uh-oh, dangling marker; this should never happen */ - g_warning ("Dangling marker %s at frame %d", - marker->name, - marker->frame_num); - } - /* this will take care of freeing the marker as well */ g_hash_table_remove (priv->markers_by_name, marker_name); } @@ -1705,8 +1424,7 @@ clutter_timeline_has_marker (ClutterTimeline *timeline, g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE); g_return_val_if_fail (marker_name != NULL, FALSE); - if (G_UNLIKELY (timeline->priv->markers_by_name == NULL || - timeline->priv->markers_by_frame == NULL)) + if (G_UNLIKELY (timeline->priv->markers_by_name == NULL)) return FALSE; return NULL != g_hash_table_lookup (timeline->priv->markers_by_name, diff --git a/clutter/clutter-timeline.h b/clutter/clutter-timeline.h index 7d829ebaa..3b372408f 100644 --- a/clutter/clutter-timeline.h +++ b/clutter/clutter-timeline.h @@ -112,17 +112,12 @@ struct _ClutterTimelineClass 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_new (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); ClutterTimelineDirection clutter_timeline_get_direction (ClutterTimeline *timeline); void clutter_timeline_set_direction (ClutterTimeline *timeline, ClutterTimelineDirection direction); @@ -134,32 +129,25 @@ void clutter_timeline_set_loop (ClutterTimeline *timeli gboolean clutter_timeline_get_loop (ClutterTimeline *timeline); void clutter_timeline_rewind (ClutterTimeline *timeline); void clutter_timeline_skip (ClutterTimeline *timeline, - guint n_frames); + guint msecs); void clutter_timeline_advance (ClutterTimeline *timeline, - guint frame_num); -gint clutter_timeline_get_current_frame (ClutterTimeline *timeline); + guint msecs); +guint clutter_timeline_get_elapsed_time (ClutterTimeline *timeline); gdouble clutter_timeline_get_progress (ClutterTimeline *timeline); CoglFixed 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); gboolean clutter_timeline_is_playing (ClutterTimeline *timeline); void clutter_timeline_set_delay (ClutterTimeline *timeline, guint msecs); guint clutter_timeline_get_delay (ClutterTimeline *timeline); -guint clutter_timeline_get_delta (ClutterTimeline *timeline, - guint *msecs); +guint clutter_timeline_get_delta (ClutterTimeline *timeline); -void clutter_timeline_add_marker_at_frame (ClutterTimeline *timeline, - const gchar *marker_name, - guint frame_num); void clutter_timeline_add_marker_at_time (ClutterTimeline *timeline, const gchar *marker_name, guint msecs); void clutter_timeline_remove_marker (ClutterTimeline *timeline, const gchar *marker_name); gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline, - gint frame_num, + gint msecs, gsize *n_markers) G_GNUC_MALLOC; gboolean clutter_timeline_has_marker (ClutterTimeline *timeline, const gchar *marker_name); diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 142d28b82..58079f476 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -542,18 +542,13 @@ clutter_stage_add ClutterTimeline ClutterTimelineClass clutter_timeline_new -clutter_timeline_new_for_duration clutter_timeline_clone -clutter_timeline_set_speed -clutter_timeline_get_speed clutter_timeline_set_duration clutter_timeline_get_duration clutter_timeline_set_loop clutter_timeline_get_loop -clutter_timeline_set_n_frames -clutter_timeline_get_n_frames clutter_timeline_set_delay clutter_timeline_get_delay ClutterTimelineDirection @@ -567,14 +562,13 @@ clutter_timeline_stop clutter_timeline_rewind clutter_timeline_skip clutter_timeline_advance -clutter_timeline_get_current_frame +clutter_timeline_get_elapsed_time clutter_timeline_get_delta clutter_timeline_get_progress clutter_timeline_get_progressx clutter_timeline_is_playing -clutter_timeline_add_marker_at_frame clutter_timeline_add_marker_at_time clutter_timeline_has_marker clutter_timeline_list_markers diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am index be19c0408..556d39278 100644 --- a/tests/conform/Makefile.am +++ b/tests/conform/Makefile.am @@ -7,10 +7,8 @@ test_conformance_SOURCES = \ test-conform-common.c \ test-conform-common.h \ \ - test-timeline-dup-frames.c \ test-timeline-interpolate.c \ test-timeline-rewind.c \ - test-timeline-smoothness.c \ test-timeline.c \ test-vertex-buffer-contiguous.c \ test-vertex-buffer-interleved.c \ diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c index fc0daacdc..22f63a541 100644 --- a/tests/conform/test-conform-main.c +++ b/tests/conform/test-conform-main.c @@ -85,11 +85,8 @@ main (int argc, char **argv) shared_state->argv_addr = &argv; TEST_CONFORM_SIMPLE ("/timeline", test_timeline); - TEST_CONFORM_SKIP (!g_test_slow (), "/timeline", test_timeline_dup_frames); - TEST_CONFORM_SKIP (!g_test_slow (), "/timeline", test_timeline_dup_frames); TEST_CONFORM_SKIP (!g_test_slow (), "/timeline", test_timeline_interpolate); TEST_CONFORM_SKIP (!g_test_slow (), "/timeline", test_timeline_rewind); - TEST_CONFORM_SKIP (!g_test_slow (), "/timeline", test_timeline_smoothness); TEST_CONFORM_SIMPLE ("/picking", test_pick); diff --git a/tests/conform/test-timeline-dup-frames.c b/tests/conform/test-timeline-dup-frames.c deleted file mode 100644 index de41f1f0e..000000000 --- a/tests/conform/test-timeline-dup-frames.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include - -#include "test-conform-common.h" - -/* We use a nice slow timeline for this test since we - * dont want the timeouts to interpolate the timeline - * forward multiple frames */ -#define TEST_TIMELINE_FPS 10 -#define TEST_TIMELINE_FRAME_COUNT 20 - -typedef struct _TestState -{ - ClutterTimeline *timeline; - gint prev_frame; - gint completion_count; - gint passed; - guint source_id; - GTimeVal prev_tick; - gulong msecs_delta; -} TestState; - -static void -new_frame_cb (ClutterTimeline *timeline, - gint frame_num, - TestState *state) -{ - gint current_frame = clutter_timeline_get_current_frame (state->timeline); - - if (state->prev_frame - != clutter_timeline_get_current_frame (state->timeline)) - { - g_test_message ("timeline previous frame=%-4i " - "actual frame=%-4i (OK)\n", - state->prev_frame, - current_frame); - } - else - { - g_test_message ("timeline previous frame=%-4i " - "actual frame=%-4i (FAILED)\n", - state->prev_frame, - current_frame); - - state->passed = FALSE; - } - - state->prev_frame = current_frame; -} - - -static void -completed_cb (ClutterTimeline *timeline, - TestState *state) -{ - state->completion_count++; - - if (state->completion_count == 2) - { - if (state->passed) - { - g_test_message ("Passed\n"); - clutter_main_quit (); - } - else - { - g_test_message ("Failed\n"); - exit (EXIT_FAILURE); - } - } -} - -static gboolean -frame_tick (gpointer data) -{ - TestState *state = data; - GTimeVal cur_tick = { 0, }; - gulong msecs; - - g_get_current_time (&cur_tick); - - if (state->prev_tick.tv_sec == 0) - state->prev_tick = cur_tick; - - msecs = (cur_tick.tv_sec - state->prev_tick.tv_sec) * 1000 - + (cur_tick.tv_usec - state->prev_tick.tv_usec) / 1000; - - if (clutter_timeline_is_playing (state->timeline)) - clutter_timeline_advance_delta (state->timeline, msecs); - - state->msecs_delta = msecs; - state->prev_tick = cur_tick; - - return TRUE; -} - -void -test_timeline_dup_frames (TestConformSimpleFixture *fixture, - gconstpointer data) -{ - TestState state; - - state.timeline = - clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, - TEST_TIMELINE_FPS); - clutter_timeline_set_loop (state.timeline, TRUE); - g_signal_connect (G_OBJECT(state.timeline), - "new-frame", - G_CALLBACK(new_frame_cb), - &state); - g_signal_connect (G_OBJECT(state.timeline), - "completed", - G_CALLBACK(completed_cb), - &state); - - state.prev_frame = -1; - state.completion_count = 0; - state.passed = TRUE; - state.prev_tick.tv_sec = 0; - state.prev_tick.tv_usec = 0; - state.msecs_delta = 0; - - state.source_id = - clutter_threads_add_frame_source (60, frame_tick, &state); - - clutter_timeline_start (state.timeline); - - clutter_main(); - - g_source_remove (state.source_id); - g_object_unref (state.timeline); -} - diff --git a/tests/conform/test-timeline-interpolate.c b/tests/conform/test-timeline-interpolate.c index 5779b0902..c4837a5ec 100644 --- a/tests/conform/test-timeline-interpolate.c +++ b/tests/conform/test-timeline-interpolate.c @@ -9,7 +9,7 @@ * will interpolate the number frames that should have * passed between timeouts. */ #define TEST_TIMELINE_FPS 1000 -#define TEST_TIMELINE_FRAME_COUNT 5000 +#define TEST_TIMELINE_DURATION 5000 /* We are at the mercy of the system scheduler so this * may not be a very reliable tolerance. */ @@ -42,7 +42,7 @@ new_frame_cb (ClutterTimeline *timeline, g_get_current_time (¤t_time); - current_frame = clutter_timeline_get_current_frame (state->timeline); + current_frame = clutter_timeline_get_elapsed_time (state->timeline); msec_diff = (current_time.tv_sec - state->start_time.tv_sec) * 1000; msec_diff += (current_time.tv_usec - state->start_time.tv_usec)/1000; @@ -50,13 +50,13 @@ new_frame_cb (ClutterTimeline *timeline, /* If we expect to have interpolated past the end of the timeline * we keep track of the overflow so we can determine when * the next timeout will happen. We then clip expected_frames - * to TEST_TIMELINE_FRAME_COUNT since clutter-timeline + * to TEST_TIMELINE_DURATION since clutter-timeline * semantics guaranty this frame is always signaled before * looping */ - if (state->expected_frame > TEST_TIMELINE_FRAME_COUNT) + if (state->expected_frame > TEST_TIMELINE_DURATION) { - loop_overflow = state->expected_frame - TEST_TIMELINE_FRAME_COUNT; - state->expected_frame = TEST_TIMELINE_FRAME_COUNT; + loop_overflow = state->expected_frame - TEST_TIMELINE_DURATION; + state->expected_frame = TEST_TIMELINE_DURATION; } if (current_frame >= (state->expected_frame-TEST_ERROR_TOLERANCE) @@ -99,10 +99,10 @@ new_frame_cb (ClutterTimeline *timeline, g_usleep (1000000); } - if (current_frame >= TEST_TIMELINE_FRAME_COUNT) + if (current_frame >= TEST_TIMELINE_DURATION) { state->expected_frame += loop_overflow; - state->expected_frame -= TEST_TIMELINE_FRAME_COUNT; + state->expected_frame -= TEST_TIMELINE_DURATION; g_test_message ("End of timeline reached: " "Wrapping expected frame too %i\n", state->expected_frame); @@ -165,8 +165,7 @@ test_timeline_interpolate (TestConformSimpleFixture *fixture, TestState state; state.timeline = - clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, - TEST_TIMELINE_FPS); + clutter_timeline_new (TEST_TIMELINE_DURATION); clutter_timeline_set_loop (state.timeline, TRUE); g_signal_connect (G_OBJECT(state.timeline), "new-frame", diff --git a/tests/conform/test-timeline-rewind.c b/tests/conform/test-timeline-rewind.c index c46e7a5ff..b1cfa13c0 100644 --- a/tests/conform/test-timeline-rewind.c +++ b/tests/conform/test-timeline-rewind.c @@ -4,8 +4,7 @@ #include "test-conform-common.h" -#define TEST_TIMELINE_FPS 10 -#define TEST_TIMELINE_FRAME_COUNT 5 +#define TEST_TIMELINE_DURATION 500 #define TEST_WATCHDOG_KICK_IN_SECONDS 10 typedef struct _TestState @@ -42,9 +41,9 @@ new_frame_cb (ClutterTimeline *timeline, gint frame_num, TestState *state) { - gint current_frame = clutter_timeline_get_current_frame (timeline); + gint elapsed_time = clutter_timeline_get_elapsed_time (timeline); - if (current_frame == TEST_TIMELINE_FRAME_COUNT) + if (elapsed_time == TEST_TIMELINE_DURATION) { g_test_message ("new-frame signal recieved (end of timeline)\n"); g_test_message ("Rewinding timeline\n"); @@ -53,7 +52,7 @@ new_frame_cb (ClutterTimeline *timeline, } else { - if (current_frame == 0) + if (elapsed_time == 0) { g_test_message ("new-frame signal recieved (start of timeline)\n"); } @@ -101,8 +100,7 @@ test_timeline_rewind (TestConformSimpleFixture *fixture, TestState state; state.timeline = - clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, - TEST_TIMELINE_FPS); + clutter_timeline_new (TEST_TIMELINE_DURATION); g_signal_connect (G_OBJECT(state.timeline), "new-frame", G_CALLBACK(new_frame_cb), diff --git a/tests/conform/test-timeline-smoothness.c b/tests/conform/test-timeline-smoothness.c deleted file mode 100644 index ab34d7e4e..000000000 --- a/tests/conform/test-timeline-smoothness.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include - -#include "test-conform-common.h" - -#define TEST_TIMELINE_FPS 10 -#define TEST_TIMELINE_FRAME_COUNT 20 -#define TEST_ERROR_TOLERANCE 5 - -typedef struct _TestState -{ - ClutterTimeline *timeline; - GTimeVal start_time; - GTimeVal prev_frame_time; - guint frame; - gint completion_count; - gint passed; - guint source_id; - GTimeVal prev_tick; - gulong msecs_delta; -} TestState; - -static void -new_frame_cb (ClutterTimeline *timeline, - gint frame_num, - TestState *state) -{ - GTimeVal current_time; - glong total_elapsed_ms; - glong frame_elapsed_ms = 0; - gchar *bump = ""; - - g_get_current_time (¤t_time); - - total_elapsed_ms = (current_time.tv_sec - state->start_time.tv_sec) * 1000; - total_elapsed_ms += (current_time.tv_usec - state->start_time.tv_usec)/1000; - - if (state->frame>0) - { - frame_elapsed_ms = - (current_time.tv_sec - state->prev_frame_time.tv_sec) * 1000; - frame_elapsed_ms += - (current_time.tv_usec - state->prev_frame_time.tv_usec)/1000; - - if (ABS(frame_elapsed_ms - (1000/TEST_TIMELINE_FPS)) - > TEST_ERROR_TOLERANCE) - { - state->passed = FALSE; - bump = " (BUMP)"; - } - } - - g_test_message ("timeline frame=%-2d total elapsed=%-4li(ms) " - "since last frame=%-4li(ms)%s\n", - clutter_timeline_get_current_frame(state->timeline), - total_elapsed_ms, - frame_elapsed_ms, - bump); - - state->prev_frame_time = current_time; - state->frame++; -} - - -static void -completed_cb (ClutterTimeline *timeline, - TestState *state) -{ - state->completion_count++; - - if (state->completion_count == 2) - { - if (state->passed) - { - g_test_message ("Passed\n"); - clutter_main_quit (); - } - else - { - g_test_message ("Failed\n"); - exit (EXIT_FAILURE); - } - } -} - -static gboolean -frame_tick (gpointer data) -{ - TestState *state = data; - GTimeVal cur_tick = { 0, }; - gulong msecs; - - g_get_current_time (&cur_tick); - - if (state->prev_tick.tv_sec == 0) - state->prev_tick = cur_tick; - - msecs = (cur_tick.tv_sec - state->prev_tick.tv_sec) * 1000 - + (cur_tick.tv_usec - state->prev_tick.tv_usec) / 1000; - - if (clutter_timeline_is_playing (state->timeline)) - clutter_timeline_advance_delta (state->timeline, msecs); - - state->msecs_delta = msecs; - state->prev_tick = cur_tick; - - return TRUE; -} - -void -test_timeline_smoothness (TestConformSimpleFixture *fixture, - gconstpointer data) -{ - TestState state; - - state.timeline = - clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, - TEST_TIMELINE_FPS); - clutter_timeline_set_loop (state.timeline, TRUE); - g_signal_connect (G_OBJECT(state.timeline), - "new-frame", - G_CALLBACK(new_frame_cb), - &state); - g_signal_connect (G_OBJECT(state.timeline), - "completed", - G_CALLBACK(completed_cb), - &state); - - state.frame = 0; - state.completion_count = 0; - state.passed = TRUE; - state.prev_tick.tv_sec = 0; - state.prev_tick.tv_usec = 0; - state.msecs_delta = 0; - - state.source_id = - clutter_threads_add_frame_source (60, frame_tick, &state); - - g_get_current_time (&state.start_time); - clutter_timeline_start (state.timeline); - - clutter_main(); - - g_source_remove (state.source_id); - g_object_unref (state.timeline); -} diff --git a/tests/conform/test-timeline.c b/tests/conform/test-timeline.c index 091440f6d..900a3feb9 100644 --- a/tests/conform/test-timeline.c +++ b/tests/conform/test-timeline.c @@ -15,6 +15,7 @@ for. */ #define FRAME_COUNT 10 +#define FPS 30 typedef struct _TimelineData TimelineData; @@ -53,13 +54,21 @@ timeline_complete_cb (ClutterTimeline *timeline, static void timeline_new_frame_cb (ClutterTimeline *timeline, - gint frame_no, + gint msec, TimelineData *data) { + /* Calculate an approximate frame number from the duration with + rounding */ + int frame_no = ((msec * FRAME_COUNT + (FRAME_COUNT * 1000 / FPS) / 2) + / (FRAME_COUNT * 1000 / FPS)); + if (g_test_verbose ()) g_print ("%i: Doing frame %d, delta = %i\n", data->timeline_num, frame_no, - clutter_timeline_get_delta (timeline, NULL)); + clutter_timeline_get_delta (timeline)); + + g_assert (frame_no >= 0 && frame_no <= FRAME_COUNT); + data->frame_hit_count[frame_no]++; } @@ -72,7 +81,7 @@ timeline_marker_reached_cb (ClutterTimeline *timeline, if (g_test_verbose ()) g_print ("%i: Marker '%s' (%d) reached, delta = %i\n", data->timeline_num, marker_name, frame_num, - clutter_timeline_get_delta (timeline, NULL)); + clutter_timeline_get_delta (timeline)); data->markers_hit = g_slist_prepend (data->markers_hit, g_strdup (marker_name)); } @@ -128,7 +137,7 @@ check_timeline (ClutterTimeline *timeline, if (check_missed_frames) { for (i = 0; i < FRAME_COUNT; i++) - if (data->frame_hit_count[i + frame_offset] != 1) + if (data->frame_hit_count[i + frame_offset] < 1) missed_frame_count++; if (missed_frame_count) @@ -230,16 +239,19 @@ test_timeline (TestConformSimpleFixture *fixture, counter = g_new0 (FrameCounter, 1); - source_id = clutter_threads_add_frame_source (60, frame_tick, counter); + source_id = clutter_threads_add_frame_source (FPS, frame_tick, counter); timeline_data_init (&data_1, 1); - timeline_1 = clutter_timeline_new (FRAME_COUNT, 30); - clutter_timeline_add_marker_at_frame (timeline_1, "foo", 5); - clutter_timeline_add_marker_at_frame (timeline_1, "bar", 5); - clutter_timeline_add_marker_at_frame (timeline_1, "baz", 5); - clutter_timeline_add_marker_at_frame (timeline_1, "near-end-marker", 9); - clutter_timeline_add_marker_at_frame (timeline_1, "end-marker", 10); - markers = clutter_timeline_list_markers (timeline_1, 5, &n_markers); + timeline_1 = clutter_timeline_new (FRAME_COUNT * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_1, "foo", 5 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_1, "bar", 5 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_1, "baz", 5 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_1, "near-end-marker", + 9 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_1, "end-marker", + 10 * 1000 / FPS); + markers = clutter_timeline_list_markers (timeline_1, 5 * 1000 / FPS, + &n_markers); g_assert (markers != NULL); g_assert (n_markers == 3); g_strfreev (markers); @@ -248,7 +260,7 @@ test_timeline (TestConformSimpleFixture *fixture, timeline_data_init (&data_2, 2); timeline_2 = clutter_timeline_clone (timeline_1); - clutter_timeline_add_marker_at_frame (timeline_2, "bar", 2); + clutter_timeline_add_marker_at_time (timeline_2, "bar", 2 * 1000 / FPS); markers = clutter_timeline_list_markers (timeline_2, -1, &n_markers); g_assert (markers != NULL); g_assert (n_markers == 1); @@ -260,10 +272,12 @@ test_timeline (TestConformSimpleFixture *fixture, timeline_data_init (&data_3, 3); timeline_3 = clutter_timeline_clone (timeline_1); clutter_timeline_set_direction (timeline_3, CLUTTER_TIMELINE_BACKWARD); - clutter_timeline_add_marker_at_frame (timeline_3, "foo", 5); - clutter_timeline_add_marker_at_frame (timeline_3, "baz", 8); - clutter_timeline_add_marker_at_frame (timeline_3, "near-end-marker", 1); - clutter_timeline_add_marker_at_frame (timeline_3, "end-marker", 0); + clutter_timeline_add_marker_at_time (timeline_3, "foo", 5 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_3, "baz", 8 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_3, "near-end-marker", + 1 * 1000 / FPS); + clutter_timeline_add_marker_at_time (timeline_3, "end-marker", + 0 * 1000 / FPS); counter->timelines = g_slist_prepend (counter->timelines, timeline_3); diff --git a/tests/interactive/test-actor-clone.c b/tests/interactive/test-actor-clone.c index 92c7f79f8..d2f15f066 100644 --- a/tests/interactive/test-actor-clone.c +++ b/tests/interactive/test-actor-clone.c @@ -105,12 +105,13 @@ frame_cb (ClutterTimeline *timeline, { SuperOH *oh = data; gint i; + float rotation = clutter_timeline_get_progress (timeline) * 360.0f; /* Rotate everything clockwise about stage center*/ clutter_actor_set_rotation (oh->group, CLUTTER_Z_AXIS, - frame_num, + rotation, oh->stage_width / 2, oh->stage_height / 2, 0); @@ -126,7 +127,7 @@ frame_cb (ClutterTimeline *timeline, */ clutter_actor_set_rotation (oh->hand[i], CLUTTER_Z_AXIS, - -6.0 * frame_num, + -6.0 * rotation, 0, 0, 0); } } @@ -178,7 +179,7 @@ test_actor_clone_main (int argc, char *argv[]) oh = g_new (SuperOH, 1); /* Create a timeline to manage animation */ - oh->timeline = clutter_timeline_new (360, 60); + oh->timeline = clutter_timeline_new (6000); clutter_timeline_set_loop (oh->timeline, TRUE); /* fire a callback for frame change */ diff --git a/tests/interactive/test-actors.c b/tests/interactive/test-actors.c index eb2c49df3..33fa2d995 100644 --- a/tests/interactive/test-actors.c +++ b/tests/interactive/test-actors.c @@ -98,17 +98,18 @@ input_cb (ClutterActor *stage, /* Timeline handler */ static void frame_cb (ClutterTimeline *timeline, - gint frame_num, + gint msecs, gpointer data) { SuperOH *oh = data; gint i; + float rotation = clutter_timeline_get_progress (timeline) * 360.0f; /* Rotate everything clockwise about stage center*/ clutter_actor_set_rotation (oh->group, CLUTTER_Z_AXIS, - frame_num, + rotation, oh->stage_width / 2, oh->stage_height / 2, 0); @@ -120,7 +121,7 @@ frame_cb (ClutterTimeline *timeline, */ clutter_actor_set_rotation (oh->hand[i], CLUTTER_Z_AXIS, - -6.0 * frame_num, + -6.0 * rotation, 0, 0, 0); } } @@ -172,7 +173,7 @@ test_actors_main (int argc, char *argv[]) oh->stage = stage; /* Create a timeline to manage animation */ - oh->timeline = clutter_timeline_new (360, 60); + oh->timeline = clutter_timeline_new (6000); clutter_timeline_set_loop (oh->timeline, TRUE); /* fire a callback for frame change */ diff --git a/tests/interactive/test-behave.c b/tests/interactive/test-behave.c index c685366df..4a794f57b 100644 --- a/tests/interactive/test-behave.c +++ b/tests/interactive/test-behave.c @@ -164,7 +164,7 @@ test_behave_main (int argc, char *argv[]) clutter_container_add (CLUTTER_CONTAINER (group), rect, hand, NULL); /* Make a timeline */ - timeline = clutter_timeline_new_for_duration (4000); /* num frames, fps */ + timeline = clutter_timeline_new (4000); /* num frames, fps */ clutter_timeline_set_loop (timeline, TRUE); g_signal_connect (timeline, "completed", G_CALLBACK (timeline_completed), diff --git a/tests/interactive/test-cogl-multitexture.c b/tests/interactive/test-cogl-multitexture.c index df7360260..9d7af690a 100644 --- a/tests/interactive/test-cogl-multitexture.c +++ b/tests/interactive/test-cogl-multitexture.c @@ -9,8 +9,6 @@ #include #include -#define TIMELINE_FRAME_COUNT 200 - typedef struct _TestMultiLayerMaterialState { ClutterActor *group; @@ -45,9 +43,7 @@ material_rectangle_paint (ClutterActor *actor, gpointer data) TestMultiLayerMaterialState *state = data; cogl_set_source (state->material); - cogl_rectangle_with_multitexture_coords (0, 0, - TIMELINE_FRAME_COUNT, - TIMELINE_FRAME_COUNT, + cogl_rectangle_with_multitexture_coords (0, 0, 200, 200, state->tex_coords, 12); } @@ -122,7 +118,7 @@ test_cogl_multitexture_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER(stage), state->group); - timeline = clutter_timeline_new (TIMELINE_FRAME_COUNT, 26 /* fps */); + timeline = clutter_timeline_new (7692); clutter_timeline_set_loop (timeline, TRUE); g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state); diff --git a/tests/interactive/test-cogl-primitives.c b/tests/interactive/test-cogl-primitives.c index 5f20e9bea..fb5adb378 100644 --- a/tests/interactive/test-cogl-primitives.c +++ b/tests/interactive/test-cogl-primitives.c @@ -81,8 +81,8 @@ static PaintFunc paint_func []= static void paint_cb (ClutterActor *self, ClutterTimeline *tl) { - gint paint_index = (clutter_timeline_get_current_frame (tl) - % G_N_ELEMENTS (paint_func)); + gint paint_index = (clutter_timeline_get_progress (tl) + * G_N_ELEMENTS (paint_func)); cogl_push_matrix (); @@ -108,8 +108,7 @@ test_cogl_primitives_main (int argc, char *argv[]) clutter_init(&argc, &argv); - /* One frame for each paint function at one frame per second */ - tl = clutter_timeline_new (G_N_ELEMENTS (paint_func), 1); + tl = clutter_timeline_new (G_N_ELEMENTS (paint_func) * 1000); clutter_timeline_set_loop (tl, TRUE); clutter_timeline_start (tl); diff --git a/tests/interactive/test-cogl-tex-polygon.c b/tests/interactive/test-cogl-tex-polygon.c index b7252b50a..0e30f74a0 100644 --- a/tests/interactive/test-cogl-tex-polygon.c +++ b/tests/interactive/test-cogl-tex-polygon.c @@ -370,7 +370,7 @@ test_cogl_tex_polygon_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); /* Timeline for animation */ - timeline = clutter_timeline_new (360, 60); /* num frames, fps */ + timeline = clutter_timeline_new (6000); clutter_timeline_set_loop (timeline, TRUE); g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); clutter_timeline_start (timeline); diff --git a/tests/interactive/test-cogl-tex-tile.c b/tests/interactive/test-cogl-tex-tile.c index 07f395db6..5d40e1344 100644 --- a/tests/interactive/test-cogl-tex-tile.c +++ b/tests/interactive/test-cogl-tex-tile.c @@ -202,7 +202,7 @@ test_cogl_tex_tile_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); /* Timeline for animation */ - timeline = clutter_timeline_new (360, 60); /* num frames, fps */ + timeline = clutter_timeline_new (6000); /* num frames, fps */ clutter_timeline_set_loop (timeline, TRUE); g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); clutter_timeline_start (timeline); diff --git a/tests/interactive/test-cogl-vertex-buffer.c b/tests/interactive/test-cogl-vertex-buffer.c index 093e32a4a..4fad21d07 100644 --- a/tests/interactive/test-cogl-vertex-buffer.c +++ b/tests/interactive/test-cogl-vertex-buffer.c @@ -59,8 +59,7 @@ frame_cb (ClutterTimeline *timeline, TestState *state) { guint x, y; - guint n_frames = clutter_timeline_get_n_frames (timeline); - float period_progress = ((float)frame_num / (float)n_frames) * 2.0 * G_PI; + float period_progress = clutter_timeline_get_progress (timeline); float period_progress_sin = sinf (period_progress); float wave_shift = period_progress * WAVE_SPEED; float ripple_shift = period_progress * RIPPLE_SPEED; @@ -354,7 +353,7 @@ test_cogl_vertex_buffer_main (int argc, char *argv[]) (stage_geom.width / 2.0) - (dummy_width / 2.0), (stage_geom.height / 2.0) - (dummy_height / 2.0)); - state.timeline = clutter_timeline_new (360, 60); + state.timeline = clutter_timeline_new (6000); clutter_timeline_set_loop (state.timeline, TRUE); g_signal_connect (state.timeline, "new-frame", diff --git a/tests/interactive/test-depth.c b/tests/interactive/test-depth.c index 2f8491077..7f5d1edd0 100644 --- a/tests/interactive/test-depth.c +++ b/tests/interactive/test-depth.c @@ -157,7 +157,7 @@ test_depth_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); /* 3 seconds, at 60 fps */ - timeline = clutter_timeline_new (180, 60); + timeline = clutter_timeline_new (3000); g_signal_connect (timeline, "completed", G_CALLBACK (timeline_completed), NULL); diff --git a/tests/interactive/test-layout.c b/tests/interactive/test-layout.c index 93783723e..5fca0e2b9 100644 --- a/tests/interactive/test-layout.c +++ b/tests/interactive/test-layout.c @@ -756,7 +756,7 @@ test_layout_main (int argc, char *argv[]) clutter_color_from_string (&bg_color, "Red"); - main_timeline = clutter_timeline_new_for_duration (2000); + main_timeline = clutter_timeline_new (2000); clutter_timeline_set_loop (main_timeline, TRUE); g_signal_connect (main_timeline, "new-frame", G_CALLBACK (relayout_on_frame), diff --git a/tests/interactive/test-multistage.c b/tests/interactive/test-multistage.c index 40caa40f6..1cc1fc8ab 100644 --- a/tests/interactive/test-multistage.c +++ b/tests/interactive/test-multistage.c @@ -72,7 +72,7 @@ on_button_press (ClutterActor *actor, win_title = g_strdup_printf ("Stage:%p", new_stage); clutter_stage_set_title (CLUTTER_STAGE(new_stage), win_title); - timeline = clutter_timeline_new_for_duration (2000); + timeline = clutter_timeline_new (2000); clutter_timeline_set_loop (timeline, TRUE); alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); diff --git a/tests/interactive/test-paint-wrapper.c b/tests/interactive/test-paint-wrapper.c index ac53221e5..e84d72c84 100644 --- a/tests/interactive/test-paint-wrapper.c +++ b/tests/interactive/test-paint-wrapper.c @@ -88,17 +88,18 @@ input_cb (ClutterStage *stage, /* Timeline handler */ static void frame_cb (ClutterTimeline *timeline, - gint frame_num, + gint msecs, gpointer data) { - SuperOH *oh = (SuperOH *)data; - gint i; + SuperOH *oh = (SuperOH *)data; + gint i; + float rotation = clutter_timeline_get_progress (timeline) * 360.0f; /* Rotate everything clockwise about stage center*/ clutter_actor_set_rotation (CLUTTER_ACTOR (oh->group), CLUTTER_Z_AXIS, - frame_num, + rotation, CLUTTER_STAGE_WIDTH () / 2, CLUTTER_STAGE_HEIGHT () / 2, 0); @@ -116,7 +117,7 @@ frame_cb (ClutterTimeline *timeline, * unit based functions to fix. */ clutter_actor_set_rotation (oh->hand[i], CLUTTER_Z_AXIS, - - 6.0 * frame_num, 0, 0, 0); + - 6.0 * rotation, 0, 0, 0); } } @@ -208,7 +209,7 @@ test_paint_wrapper_main (int argc, char *argv[]) oh = g_new(SuperOH, 1); /* Create a timeline to manage animation */ - timeline = clutter_timeline_new (360, 60); /* num frames, fps */ + timeline = clutter_timeline_new (6000); clutter_timeline_set_loop (timeline, TRUE); /* fire a callback for frame change */ diff --git a/tests/interactive/test-pixmap.c b/tests/interactive/test-pixmap.c index 882eff0b3..eb10427b7 100644 --- a/tests/interactive/test-pixmap.c +++ b/tests/interactive/test-pixmap.c @@ -233,7 +233,7 @@ test_pixmap_main (int argc, char **argv) clutter_actor_set_position (stage, 0, 150); clutter_stage_set_color (CLUTTER_STAGE (stage), &gry); - timeline = clutter_timeline_new (60*5, 60); + timeline = clutter_timeline_new (5000); g_signal_connect (timeline, "completed", G_CALLBACK (timeline_completed), NULL); diff --git a/tests/interactive/test-rotate.c b/tests/interactive/test-rotate.c index 6fea09ca0..ee11ef353 100644 --- a/tests/interactive/test-rotate.c +++ b/tests/interactive/test-rotate.c @@ -44,7 +44,7 @@ test_rotate_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); /* Make a timeline */ - timeline = clutter_timeline_new (200, 26); /* num frames, fps */ + timeline = clutter_timeline_new (7692); /* num frames, fps */ clutter_timeline_set_loop (timeline, TRUE); /* Set an alpha func to power behaviour */ diff --git a/tests/interactive/test-scale.c b/tests/interactive/test-scale.c index 7a2d86fdf..cf2a14552 100644 --- a/tests/interactive/test-scale.c +++ b/tests/interactive/test-scale.c @@ -86,7 +86,7 @@ test_scale_main (int argc, char *argv[]) clutter_group_add (CLUTTER_GROUP (stage), rect); - timeline = clutter_timeline_new_for_duration (750); + timeline = clutter_timeline_new (750); alpha = clutter_alpha_new_with_func (timeline, my_ramp_func, NULL, NULL); diff --git a/tests/interactive/test-score.c b/tests/interactive/test-score.c index b80f415c3..d5f073ddc 100644 --- a/tests/interactive/test-score.c +++ b/tests/interactive/test-score.c @@ -61,28 +61,28 @@ test_score_main (int argc, char **argv) clutter_init (&argc, &argv); - timeline_1 = clutter_timeline_new_for_duration (1000); + timeline_1 = clutter_timeline_new (1000); g_object_set_data_full (G_OBJECT (timeline_1), "timeline-name", g_strdup ("Timeline 1"), g_free); - timeline_2 = clutter_timeline_new_for_duration (1000); + timeline_2 = clutter_timeline_new (1000); clutter_timeline_add_marker_at_time (timeline_2, "foo", 500); g_object_set_data_full (G_OBJECT (timeline_2), "timeline-name", g_strdup ("Timeline 2"), g_free); - timeline_3 = clutter_timeline_new_for_duration (1000); + timeline_3 = clutter_timeline_new (1000); g_object_set_data_full (G_OBJECT (timeline_3), "timeline-name", g_strdup ("Timeline 3"), g_free); - timeline_4 = clutter_timeline_new_for_duration (1000); + timeline_4 = clutter_timeline_new (1000); g_object_set_data_full (G_OBJECT (timeline_4), "timeline-name", g_strdup ("Timeline 4"), g_free); - timeline_5 = clutter_timeline_new_for_duration (1000); + timeline_5 = clutter_timeline_new (1000); g_object_set_data_full (G_OBJECT (timeline_5), "timeline-name", g_strdup ("Timeline 5"), g_free); diff --git a/tests/interactive/test-texture-async.c b/tests/interactive/test-texture-async.c index c80171ce6..4625a35fd 100644 --- a/tests/interactive/test-texture-async.c +++ b/tests/interactive/test-texture-async.c @@ -61,7 +61,7 @@ static gboolean task (gpointer foo) for (i=0; i<3; i++) { - timeline = clutter_timeline_new (60*5, 60); + timeline = clutter_timeline_new (5000); alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); depth_behavior = clutter_behaviour_depth_new (alpha, -2500, 0); clutter_behaviour_apply (depth_behavior, image[i]); diff --git a/tests/interactive/test-texture-quality.c b/tests/interactive/test-texture-quality.c index 5501059f7..214923d25 100644 --- a/tests/interactive/test-texture-quality.c +++ b/tests/interactive/test-texture-quality.c @@ -77,7 +77,7 @@ test_texture_quality_main (int argc, char *argv[]) (clutter_actor_get_height (stage) - clutter_actor_get_height (image))/2); clutter_container_add (CLUTTER_CONTAINER (stage), image, NULL); - timeline = clutter_timeline_new (60*5, 60); + timeline = clutter_timeline_new (5000); g_signal_connect (timeline, "completed", G_CALLBACK (timeline_completed), NULL); diff --git a/tests/interactive/test-threads.c b/tests/interactive/test-threads.c index a8843329b..fb2d4d4e3 100644 --- a/tests/interactive/test-threads.c +++ b/tests/interactive/test-threads.c @@ -211,7 +211,7 @@ test_threads_main (int argc, char *argv[]) rect, progress_rect, NULL); - timeline = clutter_timeline_new (150, 50); + timeline = clutter_timeline_new (3000); clutter_timeline_set_loop (timeline, TRUE); alpha = clutter_alpha_new_full (timeline, CLUTTER_LINEAR); diff --git a/tests/interactive/test-viewport.c b/tests/interactive/test-viewport.c index 65a7f2048..f406a7439 100644 --- a/tests/interactive/test-viewport.c +++ b/tests/interactive/test-viewport.c @@ -36,7 +36,7 @@ test_viewport_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand); /* Make a timeline */ - timeline = clutter_timeline_new (200, 26); /* num frames, fps */ + timeline = clutter_timeline_new (7692); clutter_timeline_set_loop (timeline, TRUE); /* Set an alpha func to power behaviour */