From b6b9dd7c65f45dbfa8bf11c68de2ebd7cbc22e95 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 18 Mar 2008 17:54:40 +0000 Subject: [PATCH] 2008-03-18 Emmanuele Bassi * clutter.symbols: Add new symbols * clutter/clutter-score.[ch]: Use the newly added marker API on the timelines to implement attaching timelines at specific points, using either milliseconds or frames. * tests/test-score.c (main): Test the new API. --- ChangeLog | 10 + clutter.symbols | 2 + clutter/clutter-score.c | 641 ++++++++++++++++++++++++++-------------- clutter/clutter-score.h | 46 +-- tests/test-score.c | 27 +- 5 files changed, 478 insertions(+), 248 deletions(-) diff --git a/ChangeLog b/ChangeLog index 77df2cbd0..5728be847 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-03-18 Emmanuele Bassi + + * clutter.symbols: Add new symbols + + * clutter/clutter-score.[ch]: Use the newly added marker API + on the timelines to implement attaching timelines at specific + points, using either milliseconds or frames. + + * tests/test-score.c (main): Test the new API. + 2008-03-18 Emmanuele Bassi * clutter/clutter-marshal.list: Add signature for the diff --git a/clutter.symbols b/clutter.symbols index 3556c2549..c5cc26c1d 100644 --- a/clutter.symbols +++ b/clutter.symbols @@ -442,6 +442,8 @@ clutter_redraw clutter_rotate_axis_get_type clutter_rotate_direction_get_type clutter_score_append +clutter_score_append_at_frame +clutter_score_append_at_time clutter_score_get_loop clutter_score_get_timeline clutter_score_get_type diff --git a/clutter/clutter-score.c b/clutter/clutter-score.c index ccbc966c7..f65cae5f8 100644 --- a/clutter/clutter-score.c +++ b/clutter/clutter-score.c @@ -38,7 +38,7 @@ * For example, this code will start two #ClutterTimelines after * a third timeline terminates: * - * + * |[ * ClutterTimeline *timeline_1, *timeline_2, *timeline_3; * ClutterScore *score; * @@ -52,12 +52,17 @@ * clutter_score_append (score, timeline_1, timeline_3); * * clutter_score_start (); - * + * ]| * * A #ClutterScore takes a reference on the timelines it manages. * - * New timelines can be added to the #ClutterScore using + * New timelines can be appended to the #ClutterScore using * clutter_score_append() and removed using clutter_score_remove(). + * Timelines can either be appended at the end of other timelines + * or at the beginning of the score using clutter_score_append(). + * Timelines can also be appeneded at a specific position, expressed + * in either millisecond or frame number, of the parent timeline, + * using clutter_score_append_at_time() or clutter_score_append_at_frame(). * * The score can be cleared using clutter_score_remove_all(). * @@ -81,15 +86,29 @@ #include "clutter-private.h" #include "clutter-debug.h" +typedef enum { + SCORE_ENTRY_TIME, + SCORE_ENTRY_FRAME, + SCORE_ENTRY_APPEND +} ClutterScoreEntryType; + typedef struct _ClutterScoreEntry ClutterScoreEntry; struct _ClutterScoreEntry { - ClutterTimeline *timeline; - guint id; + ClutterScoreEntryType type; - /* signal handler id */ - gulong completed_id; + gchar *id; + + ClutterTimeline *timeline; + ClutterTimeline *parent; + + guint msecs; + guint frame; + + /* signal handlers id */ + guint complete_id; + guint marker_id; ClutterScore *score; @@ -130,6 +149,8 @@ enum LAST_SIGNAL }; +static inline void clutter_score_clear (ClutterScore *score); + G_DEFINE_TYPE (ClutterScore, clutter_score, G_TYPE_OBJECT); static int score_signals[LAST_SIGNAL] = { 0 }; @@ -177,26 +198,14 @@ clutter_score_get_property (GObject *gobject, static void clutter_score_finalize (GObject *object) { - ClutterScorePrivate *priv = CLUTTER_SCORE (object)->priv; + ClutterScore *score = CLUTTER_SCORE (object); - if (priv->running_timelines) - g_hash_table_destroy (priv->running_timelines); + clutter_score_stop (score); + clutter_score_clear (score); G_OBJECT_CLASS (clutter_score_parent_class)->finalize (object); } -static void -clutter_score_dispose (GObject *object) -{ - ClutterScore *self = CLUTTER_SCORE(object); - ClutterScorePrivate *priv; - - priv = self->priv; - - G_OBJECT_CLASS (clutter_score_parent_class)->dispose (object); -} - - static void clutter_score_class_init (ClutterScoreClass *klass) { @@ -205,7 +214,6 @@ clutter_score_class_init (ClutterScoreClass *klass) gobject_class->set_property = clutter_score_set_property; gobject_class->get_property = clutter_score_get_property; gobject_class->finalize = clutter_score_finalize; - gobject_class->dispose = clutter_score_dispose; g_type_class_add_private (klass, sizeof (ClutterScorePrivate)); @@ -411,6 +419,178 @@ clutter_score_is_playing (ClutterScore *score) return (g_hash_table_size (score->priv->running_timelines) != 0); } +typedef enum { + FIND_BY_TIMELINE, + FIND_BY_ID, + REMOVE_BY_ID, + LIST_TIMELINES +} TraverseAction; + +typedef struct { + TraverseAction action; + + ClutterScore *score; + + /* parameters */ + union { + ClutterTimeline *timeline; + const gchar *id; + ClutterScoreEntry *entry; + } d; + + gpointer result; +} TraverseClosure; + +static gboolean +destroy_entry (GNode *node, + G_GNUC_UNUSED gpointer data) +{ + ClutterScoreEntry *entry = node->data; + + if (G_LIKELY (entry != NULL)) + { + if (entry->marker_id) + { + g_signal_handler_disconnect (entry->parent, entry->marker_id); + entry->marker_id = 0; + } + + if (entry->complete_id) + { + g_signal_handler_disconnect (entry->timeline, entry->complete_id); + entry->complete_id = 0; + } + + g_object_unref (entry->timeline); + g_free (entry->id); + g_slice_free (ClutterScoreEntry, entry); + + node->data = NULL; + } + + /* continue */ + return FALSE; +} + +/* multi-purpose traversal function for the N-ary tree used by the score */ +static gboolean +traverse_children (GNode *node, + gpointer data) +{ + TraverseClosure *closure = data; + ClutterScoreEntry *entry = node->data; + gboolean retval = FALSE; + + /* root */ + if (!entry) + return TRUE; + + switch (closure->action) + { + case FIND_BY_TIMELINE: + if (closure->d.timeline == entry->timeline) + { + closure->result = node; + retval = TRUE; + } + break; + + case FIND_BY_ID: + if (strcmp (closure->d.id, entry->id) == 0) + { + closure->result = node; + retval = TRUE; + } + break; + + case REMOVE_BY_ID: + if (strcmp (closure->d.id, entry->id) == 0) + { + if (entry->complete_id) + { + g_signal_handler_disconnect (entry->timeline, entry->complete_id); + entry->complete_id = 0; + } + + if (entry->marker_id) + { + g_signal_handler_disconnect (entry->timeline, entry->marker_id); + entry->marker_id = 0; + } + + g_object_unref (entry->timeline); + g_free (entry->id); + + g_node_traverse (node, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + destroy_entry, NULL); + + g_slice_free (ClutterScoreEntry, entry); + + closure->result = node; + retval = TRUE; + } + break; + + case LIST_TIMELINES: + closure->result = g_slist_prepend (closure->result, entry->timeline); + retval = FALSE; + break; + } + + return retval; +} + +static GNode * +find_entry_by_timeline (ClutterScore *score, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv = score->priv; + TraverseClosure closure; + + closure.action = FIND_BY_TIMELINE; + closure.score = score; + closure.d.timeline = timeline; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + if (closure.result) + return closure.result; + + return NULL; +} + +static GNode * +find_entry_by_id (ClutterScore *score, + const gchar *id) +{ + ClutterScorePrivate *priv = score->priv; + TraverseClosure closure; + + closure.action = FIND_BY_ID; + closure.score = score; + closure.d.id = id; + closure.result = NULL; + + g_node_traverse (priv->root, + G_POST_ORDER, + G_TRAVERSE_ALL, + -1, + traverse_children, &closure); + + if (closure.result) + return closure.result; + + return NULL; +} + /* forward declaration */ static void start_entry (ClutterScoreEntry *entry); @@ -424,18 +604,42 @@ start_children_entries (GNode *node, } static void -on_timeline_finish (ClutterTimeline *timeline, - ClutterScoreEntry *entry) +on_timeline_marker (ClutterTimeline *timeline, + const gchar *marker_name, + gint frame_num, + ClutterScoreEntry *entry) +{ + GNode *parent; + CLUTTER_NOTE (SCHEDULER, "timeline [%p] marker ('%s') reached", + entry->timeline, + entry->id); + + parent = find_entry_by_timeline (entry->score, timeline); + if (!parent) + return; + + /* start every child */ + if (parent->children) + { + g_node_children_foreach (parent, + G_TRAVERSE_ALL, + start_children_entries, + NULL); + } +} + +static void +on_timeline_completed (ClutterTimeline *timeline, + ClutterScoreEntry *entry) { ClutterScorePrivate *priv = entry->score->priv; - g_hash_table_remove (priv->running_timelines, - GINT_TO_POINTER (entry->id)); + g_hash_table_remove (priv->running_timelines, entry->id); - g_signal_handler_disconnect (timeline, entry->completed_id); - entry->completed_id = 0; + g_signal_handler_disconnect (timeline, entry->complete_id); + entry->complete_id = 0; - CLUTTER_NOTE (SCHEDULER, "timeline [%p] (%d) completed", + CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%s') completed", entry->timeline, entry->id); @@ -470,21 +674,22 @@ start_entry (ClutterScoreEntry *entry) { ClutterScorePrivate *priv = entry->score->priv; - entry->completed_id = - g_signal_connect (entry->timeline, - "completed", G_CALLBACK (on_timeline_finish), - entry); + if (clutter_timeline_is_playing (entry->timeline)) + return; - CLUTTER_NOTE (SCHEDULER, "timeline [%p] (%d) started", + entry->complete_id = g_signal_connect (entry->timeline, + "completed", + G_CALLBACK (on_timeline_completed), + entry); + + CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%s') started", entry->timeline, entry->id); if (G_UNLIKELY (priv->running_timelines == NULL)) - priv->running_timelines = g_hash_table_new (NULL, NULL); + priv->running_timelines = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (priv->running_timelines, - GINT_TO_POINTER (entry->id), - entry); + g_hash_table_insert (priv->running_timelines, entry->id, entry); clutter_timeline_start (entry->timeline); @@ -499,7 +704,8 @@ foreach_running_timeline_start (gpointer key, { ClutterScoreEntry *entry = value; - clutter_timeline_start (entry->timeline); + if (!clutter_timeline_is_playing (entry->timeline)) + clutter_timeline_start (entry->timeline); } /** @@ -564,11 +770,14 @@ clutter_score_stop (ClutterScore *score) priv = score->priv; - g_hash_table_foreach_remove (priv->running_timelines, - foreach_running_timeline_stop, - NULL); - g_hash_table_destroy (priv->running_timelines); - priv->running_timelines = NULL; + if (priv->running_timelines) + { + g_hash_table_foreach_remove (priv->running_timelines, + foreach_running_timeline_stop, + NULL); + g_hash_table_destroy (priv->running_timelines); + priv->running_timelines = NULL; + } } /** @@ -633,161 +842,23 @@ clutter_score_pause (ClutterScore *score) g_signal_emit (score, score_signals[PAUSED], 0); } -typedef enum { - FIND_BY_TIMELINE, - FIND_BY_ID, - REMOVE_BY_ID, - LIST_TIMELINES -} TraverseAction; - -typedef struct { - TraverseAction action; - - ClutterScore *score; - - /* parameters */ - union { - ClutterTimeline *timeline; - guint id; - ClutterScoreEntry *entry; - } d; - - gpointer result; -} TraverseClosure; - -static gboolean -destroy_entry (GNode *node, - G_GNUC_UNUSED gpointer data) -{ - ClutterScoreEntry *entry = node->data; - - if (G_LIKELY (entry != NULL)) - { - if (entry->completed_id) - g_signal_handler_disconnect (entry->timeline, entry->completed_id); - - g_object_unref (entry->timeline); - g_slice_free (ClutterScoreEntry, entry); - - node->data = NULL; - } - - /* continue */ - return FALSE; -} - -/* multi-purpose traversal function for the N-ary tree used by the score */ -static gboolean -traverse_children (GNode *node, - gpointer data) -{ - TraverseClosure *closure = data; - ClutterScoreEntry *entry = node->data; - gboolean retval = FALSE; - - /* root */ - if (!entry) - return TRUE; - - switch (closure->action) - { - case FIND_BY_TIMELINE: - if (closure->d.timeline == entry->timeline) - { - closure->result = node; - retval = TRUE; - } - break; - - case FIND_BY_ID: - if (closure->d.id == entry->id) - { - closure->result = node; - retval = TRUE; - } - break; - - case REMOVE_BY_ID: - if (closure->d.id == entry->id) - { - if (entry->completed_id) - g_signal_handler_disconnect (entry->timeline, entry->completed_id); - - g_object_unref (entry->timeline); - - g_node_traverse (node, - G_POST_ORDER, - G_TRAVERSE_ALL, - -1, - destroy_entry, NULL); - - g_slice_free (ClutterScoreEntry, entry); - - closure->result = node; - retval = TRUE; - } - break; - - case LIST_TIMELINES: - closure->result = g_slist_prepend (closure->result, entry->timeline); - retval = FALSE; - break; - } - - return retval; -} - -static GNode * -find_entry_by_timeline (ClutterScore *score, - ClutterTimeline *timeline) +static inline void +clutter_score_clear (ClutterScore *score) { ClutterScorePrivate *priv = score->priv; - TraverseClosure closure; - - closure.action = FIND_BY_TIMELINE; - closure.score = score; - closure.d.timeline = timeline; - closure.result = NULL; g_node_traverse (priv->root, G_POST_ORDER, G_TRAVERSE_ALL, -1, - traverse_children, &closure); - - if (closure.result) - return closure.result; - - return NULL; -} - -static GNode * -find_entry_by_id (ClutterScore *score, - guint id) -{ - ClutterScorePrivate *priv = score->priv; - TraverseClosure closure; - - closure.action = FIND_BY_ID; - closure.score = score; - closure.d.id = id; - closure.result = NULL; - - g_node_traverse (priv->root, - G_POST_ORDER, - G_TRAVERSE_ALL, - -1, - traverse_children, &closure); - - if (closure.result) - return closure.result; - - return NULL; + destroy_entry, NULL); + g_node_destroy (priv->root); } /** * clutter_score_append: * @score: a #ClutterScore + * @id: a unique string identifying the timeline * @parent: a #ClutterTimeline in the score or %NULL * @timeline: a #ClutterTimeline * @@ -799,21 +870,20 @@ find_entry_by_id (ClutterScore *score, * * #ClutterScore will take a reference on @timeline. * - * Return value: the id of the newly added timeline, to be used with - * clutter_score_get_timeline() and clutter_score_remove(). - * - * Since: 0.6 + * Since: 0.8 */ -guint +void clutter_score_append (ClutterScore *score, + const gchar *id, ClutterTimeline *parent, ClutterTimeline *timeline) { ClutterScorePrivate *priv; - g_return_val_if_fail (CLUTTER_IS_SCORE (score), 0); - g_return_val_if_fail (parent == NULL || CLUTTER_IS_TIMELINE (parent), 0); - g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0); + g_return_if_fail (CLUTTER_IS_SCORE (score)); + g_return_if_fail (id != NULL); + g_return_if_fail (parent == NULL || CLUTTER_IS_TIMELINE (parent)); + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); priv = score->priv; @@ -822,17 +892,14 @@ clutter_score_append (ClutterScore *score, ClutterScoreEntry *entry; entry = g_slice_new (ClutterScoreEntry); - + entry->type = SCORE_ENTRY_APPEND; entry->timeline = g_object_ref (timeline); - entry->id = priv->last_id; - entry->completed_id = 0; + entry->parent = NULL; + entry->id = g_strdup (id); + entry->marker_id = 0; entry->score = score; entry->node = g_node_append_data (priv->root, entry); - - priv->last_id += 1; - - return entry->id; } else { @@ -843,23 +910,159 @@ clutter_score_append (ClutterScore *score, if (G_UNLIKELY (!node)) { g_warning ("Unable to find the parent timeline inside the score."); - return 0; + return; } entry = g_slice_new (ClutterScoreEntry); + entry->type = SCORE_ENTRY_APPEND; entry->timeline = g_object_ref (timeline); - entry->id = priv->last_id; - entry->completed_id = 0; + entry->parent = parent; + entry->id = g_strdup (id); + entry->marker_id = 0; entry->score = score; entry->node = g_node_append_data (node, entry); + } +} - priv->last_id += 1; +/** + * clutter_score_append_at_time: + * @score: a #ClutterScore + * @id: a unique string identifying the timeline + * @parent: the parent #ClutterTimeline + * @msecs: the time on @parent where the new timeline should + * be appended, in milliseconds + * @timeline: the #ClutterTimeline to append + * + * Appends @timeline at the given position on the @parent timeline, + * expressed in milliseconds. + * + * This function implicitly creates a timeline marker (see + * clutter_timeline_add_marker_at_time()) with the given @id on + * @parent. + * + * If you want to append @timeline at the end of @parent, use + * clutter_score_append(). + * + * Since: 0.8 + */ +void +clutter_score_append_at_time (ClutterScore *score, + const gchar *id, + ClutterTimeline *parent, + guint msecs, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv; + GNode *node; + ClutterScoreEntry *entry; + gchar *marker_reached_signal; - return entry->id; + g_return_if_fail (CLUTTER_IS_SCORE (score)); + g_return_if_fail (id != NULL); + g_return_if_fail (CLUTTER_IS_TIMELINE (parent)); + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = score->priv; + + node = find_entry_by_timeline (score, parent); + if (G_UNLIKELY (!node)) + { + g_warning ("Unable to find the parent timeline inside the score."); + return; } - return 0; + entry = g_slice_new (ClutterScoreEntry); + entry->type = SCORE_ENTRY_TIME; + entry->timeline = g_object_ref (timeline); + entry->parent = parent; + entry->msecs = msecs; + entry->id = g_strdup (id); + entry->score = score; + + clutter_timeline_add_marker_at_time (entry->parent, + entry->id, + entry->msecs); + + marker_reached_signal = g_strdup_printf ("marker-reached::%s", entry->id); + entry->marker_id = g_signal_connect (entry->parent, + marker_reached_signal, + G_CALLBACK (on_timeline_marker), + entry); + + entry->node = g_node_append_data (node, entry); + + g_free (marker_reached_signal); +} + +/** + * clutter_score_append_at_frame: + * @score: a #ClutterScore + * @id: a unique string identifying the timeline + * @parent: the parent #ClutterTimeline + * @msecs: the frame of @parent where the new timeline should + * be appended to + * @timeline: the #ClutterTimeline to append + * + * Appends @timeline at the given position on the @parent timeline, + * expressed as a frame number. + * + * This function implicitly creates a timeline marker (see + * clutter_timeline_add_marker_at_frame()) with the given @id + * on @parent. + * + * If you want to append @timeline at the end of @parent, use + * clutter_score_append(). + * + * Since: 0.8 + */ +void +clutter_score_append_at_frame (ClutterScore *score, + const gchar *id, + ClutterTimeline *parent, + guint frame, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv; + GNode *node; + ClutterScoreEntry *entry; + gchar *marker_reached_signal; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + g_return_if_fail (id != NULL); + g_return_if_fail (CLUTTER_IS_TIMELINE (parent)); + g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); + + priv = score->priv; + + node = find_entry_by_timeline (score, parent); + if (G_UNLIKELY (!node)) + { + g_warning ("Unable to find the parent timeline inside the score."); + return; + } + + entry = g_slice_new (ClutterScoreEntry); + entry->type = SCORE_ENTRY_TIME; + entry->timeline = g_object_ref (timeline); + entry->parent = parent; + entry->frame = frame; + entry->id = g_strdup (id); + entry->score = score; + + clutter_timeline_add_marker_at_frame (entry->parent, + entry->id, + entry->frame); + + marker_reached_signal = g_strdup_printf ("marker-reached::%s", entry->id); + entry->marker_id = g_signal_connect (entry->parent, + marker_reached_signal, + G_CALLBACK (on_timeline_marker), + entry); + + entry->node = g_node_append_data (node, entry); + + g_free (marker_reached_signal); } /** @@ -871,11 +1074,11 @@ clutter_score_append (ClutterScore *score, * the timeline has other timelines attached to it, those are removed * as well. * - * Since: 0.6 + * Since: 0.8 */ void clutter_score_remove (ClutterScore *score, - guint id) + const gchar *id) { ClutterScorePrivate *priv; TraverseClosure closure; @@ -915,17 +1118,13 @@ clutter_score_remove_all (ClutterScore *score) g_return_if_fail (CLUTTER_IS_SCORE (score)); + priv = score->priv; + /* this will take care of the running timelines */ clutter_score_stop (score); - priv = score->priv; - - g_node_traverse (priv->root, - G_POST_ORDER, - G_TRAVERSE_ALL, - -1, - destroy_entry, NULL); - g_node_destroy (priv->root); + /* destroy all the contents of the tree */ + clutter_score_clear (score); /* recreate the sentinel */ priv->root = g_node_new (NULL); @@ -941,11 +1140,11 @@ clutter_score_remove_all (ClutterScore *score) * Return value: the requested timeline, or %NULL. This function does * not increase the reference count on the returned #ClutterTimeline * - * Since: 0.6 + * Since: 0.8 */ ClutterTimeline * clutter_score_get_timeline (ClutterScore *score, - guint id) + const gchar *id) { GNode *node; ClutterScoreEntry *entry; diff --git a/clutter/clutter-score.h b/clutter/clutter-score.h index 8de88635b..f06e23577 100644 --- a/clutter/clutter-score.h +++ b/clutter/clutter-score.h @@ -76,25 +76,37 @@ struct _ClutterScoreClass GType clutter_score_get_type (void) G_GNUC_CONST; ClutterScore * clutter_score_new (void); -void clutter_score_set_loop (ClutterScore *score, - gboolean loop); -gboolean clutter_score_get_loop (ClutterScore *score); -guint clutter_score_append (ClutterScore *score, - ClutterTimeline *parent, - ClutterTimeline *timeline); -void clutter_score_remove (ClutterScore *score, - guint id); -void clutter_score_remove_all (ClutterScore *score); -ClutterTimeline *clutter_score_get_timeline (ClutterScore *score, - guint id); -GSList * clutter_score_list_timelines (ClutterScore *score); +void clutter_score_set_loop (ClutterScore *score, + gboolean loop); +gboolean clutter_score_get_loop (ClutterScore *score); -void clutter_score_start (ClutterScore *score); -void clutter_score_stop (ClutterScore *score); -void clutter_score_pause (ClutterScore *score); -void clutter_score_rewind (ClutterScore *score); -gboolean clutter_score_is_playing (ClutterScore *score); +void clutter_score_append_at_time (ClutterScore *score, + const gchar *id, + ClutterTimeline *parent, + guint msecs, + ClutterTimeline *timeline); +void clutter_score_append_at_frame (ClutterScore *score, + const gchar *id, + ClutterTimeline *parent, + guint frame, + ClutterTimeline *timeline); +void clutter_score_append (ClutterScore *score, + const gchar *id, + ClutterTimeline *parent, + ClutterTimeline *timeline); +void clutter_score_remove (ClutterScore *score, + const gchar *id); +void clutter_score_remove_all (ClutterScore *score); +ClutterTimeline *clutter_score_get_timeline (ClutterScore *score, + const gchar *id); +GSList * clutter_score_list_timelines (ClutterScore *score); + +void clutter_score_start (ClutterScore *score); +void clutter_score_stop (ClutterScore *score); +void clutter_score_pause (ClutterScore *score); +void clutter_score_rewind (ClutterScore *score); +gboolean clutter_score_is_playing (ClutterScore *score); G_END_DECLS diff --git a/tests/test-score.c b/tests/test-score.c index 9b6439b87..b86805a25 100644 --- a/tests/test-score.c +++ b/tests/test-score.c @@ -42,31 +42,35 @@ main (int argc, char **argv) ClutterTimeline *timeline_2; ClutterTimeline *timeline_3; ClutterTimeline *timeline_4; + ClutterTimeline *timeline_5; GSList *timelines; - guint t1, t2, t3, t4; clutter_init (&argc, &argv); - timeline_1 = clutter_timeline_new (10, 120); + timeline_1 = clutter_timeline_new_for_duration (1000); g_object_set_data_full (G_OBJECT (timeline_1), "timeline-name", g_strdup ("Timeline 1"), g_free); - timeline_2 = clutter_timeline_clone (timeline_1); + timeline_2 = clutter_timeline_new_for_duration (1000); g_object_set_data_full (G_OBJECT (timeline_2), "timeline-name", g_strdup ("Timeline 2"), g_free); - timeline_3 = clutter_timeline_clone (timeline_1); + timeline_3 = clutter_timeline_new_for_duration (1000); g_object_set_data_full (G_OBJECT (timeline_3), "timeline-name", g_strdup ("Timeline 3"), g_free); - timeline_4 = clutter_timeline_clone (timeline_1); + timeline_4 = clutter_timeline_new_for_duration (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); + g_object_set_data_full (G_OBJECT (timeline_5), + "timeline-name", g_strdup ("Timeline 5"), + g_free); score = clutter_score_new(); g_signal_connect (score, "timeline-started", @@ -79,13 +83,15 @@ main (int argc, char **argv) G_CALLBACK (clutter_main_quit), NULL); - t1 = clutter_score_append (score, NULL, timeline_1); - t2 = clutter_score_append (score, timeline_1, timeline_2); - t3 = clutter_score_append (score, timeline_1, timeline_3); - t4 = clutter_score_append (score, timeline_3, timeline_4); + clutter_score_append (score, "line-0", NULL, timeline_1); + clutter_score_append (score, "line-1", timeline_1, timeline_2); + clutter_score_append (score, "line-2", timeline_1, timeline_3); + clutter_score_append (score, "line-3", timeline_3, timeline_4); + + clutter_score_append_at_time (score, "line-4", timeline_2, 500, timeline_5); timelines = clutter_score_list_timelines (score); - g_assert (4 == g_slist_length (timelines)); + g_assert (5 == g_slist_length (timelines)); g_slist_free (timelines); clutter_score_start (score); @@ -96,6 +102,7 @@ main (int argc, char **argv) g_object_unref (timeline_2); g_object_unref (timeline_3); g_object_unref (timeline_4); + g_object_unref (timeline_5); g_object_unref (score); return EXIT_SUCCESS;