2008-03-18 Emmanuele Bassi <ebassi@openedhand.com>

* clutter/clutter-score.[ch]: Remove all the API changes, and
	just add a clutter_score_append_at_marker(); the implementation
	remains the same, but the marker must be explicitly created by
	the developer. The ids are no longer used to create implicit
	markers, so they can return to be unsigned integers.

	* clutter/clutter-timeline.[ch]:
	(clutter_timeline_has_marker): Add a function to query a timeline
	for a marker being set.

	* tests/test-score.c (main): Update with the API changes.

	* clutter.symbols: Update exported symbols.
This commit is contained in:
Emmanuele Bassi 2008-03-18 22:07:17 +00:00
parent 0ca514a35f
commit 477db755b7
9 changed files with 143 additions and 177 deletions

View File

@ -1,3 +1,19 @@
2008-03-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-score.[ch]: Remove all the API changes, and
just add a clutter_score_append_at_marker(); the implementation
remains the same, but the marker must be explicitly created by
the developer. The ids are no longer used to create implicit
markers, so they can return to be unsigned integers.
* clutter/clutter-timeline.[ch]:
(clutter_timeline_has_marker): Add a function to query a timeline
for a marker being set.
* tests/test-score.c (main): Update with the API changes.
* clutter.symbols: Update exported symbols.
2008-03-18 Emmanuele Bassi <ebassi@openedhand.com> 2008-03-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-texture.c: Small clean ups in the coding style. * clutter/clutter-texture.c: Small clean ups in the coding style.

View File

@ -442,8 +442,7 @@ clutter_redraw
clutter_rotate_axis_get_type clutter_rotate_axis_get_type
clutter_rotate_direction_get_type clutter_rotate_direction_get_type
clutter_score_append clutter_score_append
clutter_score_append_at_frame clutter_score_append_at_marker
clutter_score_append_at_time
clutter_score_get_loop clutter_score_get_loop
clutter_score_get_timeline clutter_score_get_timeline
clutter_score_get_type clutter_score_get_type
@ -557,6 +556,7 @@ clutter_timeline_get_loop
clutter_timeline_get_n_frames clutter_timeline_get_n_frames
clutter_timeline_get_speed clutter_timeline_get_speed
clutter_timeline_get_type clutter_timeline_get_type
clutter_timeline_has_marker
clutter_timeline_is_playing clutter_timeline_is_playing
clutter_timeline_list_markers clutter_timeline_list_markers
clutter_timeline_new clutter_timeline_new

View File

@ -86,25 +86,18 @@
#include "clutter-private.h" #include "clutter-private.h"
#include "clutter-debug.h" #include "clutter-debug.h"
typedef enum {
SCORE_ENTRY_TIME,
SCORE_ENTRY_FRAME,
SCORE_ENTRY_APPEND
} ClutterScoreEntryType;
typedef struct _ClutterScoreEntry ClutterScoreEntry; typedef struct _ClutterScoreEntry ClutterScoreEntry;
struct _ClutterScoreEntry struct _ClutterScoreEntry
{ {
ClutterScoreEntryType type; /* the entry unique id */
guint id;
gchar *id;
ClutterTimeline *timeline; ClutterTimeline *timeline;
ClutterTimeline *parent; ClutterTimeline *parent;
guint msecs; /* the optional marker */
guint frame; gchar *marker;
/* signal handlers id */ /* signal handlers id */
guint complete_id; guint complete_id;
@ -434,7 +427,7 @@ typedef struct {
/* parameters */ /* parameters */
union { union {
ClutterTimeline *timeline; ClutterTimeline *timeline;
const gchar *id; guint id;
ClutterScoreEntry *entry; ClutterScoreEntry *entry;
} d; } d;
@ -462,7 +455,7 @@ destroy_entry (GNode *node,
} }
g_object_unref (entry->timeline); g_object_unref (entry->timeline);
g_free (entry->id); g_free (entry->marker);
g_slice_free (ClutterScoreEntry, entry); g_slice_free (ClutterScoreEntry, entry);
node->data = NULL; node->data = NULL;
@ -496,7 +489,7 @@ traverse_children (GNode *node,
break; break;
case FIND_BY_ID: case FIND_BY_ID:
if (strcmp (closure->d.id, entry->id) == 0) if (closure->d.id == entry->id)
{ {
closure->result = node; closure->result = node;
retval = TRUE; retval = TRUE;
@ -504,7 +497,7 @@ traverse_children (GNode *node,
break; break;
case REMOVE_BY_ID: case REMOVE_BY_ID:
if (strcmp (closure->d.id, entry->id) == 0) if (closure->d.id == entry->id)
{ {
if (entry->complete_id) if (entry->complete_id)
{ {
@ -519,7 +512,6 @@ traverse_children (GNode *node,
} }
g_object_unref (entry->timeline); g_object_unref (entry->timeline);
g_free (entry->id);
g_node_traverse (node, g_node_traverse (node,
G_POST_ORDER, G_POST_ORDER,
@ -527,6 +519,7 @@ traverse_children (GNode *node,
-1, -1,
destroy_entry, NULL); destroy_entry, NULL);
g_free (entry->marker);
g_slice_free (ClutterScoreEntry, entry); g_slice_free (ClutterScoreEntry, entry);
closure->result = node; closure->result = node;
@ -569,7 +562,7 @@ find_entry_by_timeline (ClutterScore *score,
static GNode * static GNode *
find_entry_by_id (ClutterScore *score, find_entry_by_id (ClutterScore *score,
const gchar *id) guint id)
{ {
ClutterScorePrivate *priv = score->priv; ClutterScorePrivate *priv = score->priv;
TraverseClosure closure; TraverseClosure closure;
@ -612,7 +605,7 @@ on_timeline_marker (ClutterTimeline *timeline,
GNode *parent; GNode *parent;
CLUTTER_NOTE (SCHEDULER, "timeline [%p] marker ('%s') reached", CLUTTER_NOTE (SCHEDULER, "timeline [%p] marker ('%s') reached",
entry->timeline, entry->timeline,
entry->id); entry->marker);
parent = find_entry_by_timeline (entry->score, timeline); parent = find_entry_by_timeline (entry->score, timeline);
if (!parent) if (!parent)
@ -634,12 +627,13 @@ on_timeline_completed (ClutterTimeline *timeline,
{ {
ClutterScorePrivate *priv = entry->score->priv; ClutterScorePrivate *priv = entry->score->priv;
g_hash_table_remove (priv->running_timelines, entry->id); g_hash_table_remove (priv->running_timelines,
GUINT_TO_POINTER (entry->id));
g_signal_handler_disconnect (timeline, entry->complete_id); g_signal_handler_disconnect (timeline, entry->complete_id);
entry->complete_id = 0; entry->complete_id = 0;
CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%s') completed", CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%d') completed",
entry->timeline, entry->timeline,
entry->id); entry->id);
@ -682,14 +676,16 @@ start_entry (ClutterScoreEntry *entry)
G_CALLBACK (on_timeline_completed), G_CALLBACK (on_timeline_completed),
entry); entry);
CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%s') started", CLUTTER_NOTE (SCHEDULER, "timeline [%p] ('%d') started",
entry->timeline, entry->timeline,
entry->id); entry->id);
if (G_UNLIKELY (priv->running_timelines == NULL)) if (G_UNLIKELY (priv->running_timelines == NULL))
priv->running_timelines = g_hash_table_new (g_str_hash, g_str_equal); priv->running_timelines = g_hash_table_new (NULL, NULL);
g_hash_table_insert (priv->running_timelines, entry->id, entry); g_hash_table_insert (priv->running_timelines,
GUINT_TO_POINTER (entry->id),
entry);
clutter_timeline_start (entry->timeline); clutter_timeline_start (entry->timeline);
@ -858,7 +854,6 @@ clutter_score_clear (ClutterScore *score)
/** /**
* clutter_score_append: * clutter_score_append:
* @score: a #ClutterScore * @score: a #ClutterScore
* @id: a unique string identifying the timeline
* @parent: a #ClutterTimeline in the score or %NULL * @parent: a #ClutterTimeline in the score or %NULL
* @timeline: a #ClutterTimeline * @timeline: a #ClutterTimeline
* *
@ -870,32 +865,32 @@ clutter_score_clear (ClutterScore *score)
* *
* #ClutterScore will take a reference on @timeline. * #ClutterScore will take a reference on @timeline.
* *
* Since: 0.8 * Return value: the id of the #ClutterTimeline inside the score, or
* 0 on failure. The returned id can be used with clutter_score_remove()
* or clutter_score_get_timeline().
*
* Since: 0.6
*/ */
void guint
clutter_score_append (ClutterScore *score, clutter_score_append (ClutterScore *score,
const gchar *id,
ClutterTimeline *parent, ClutterTimeline *parent,
ClutterTimeline *timeline) ClutterTimeline *timeline)
{ {
ClutterScorePrivate *priv; ClutterScorePrivate *priv;
ClutterScoreEntry *entry;
g_return_if_fail (CLUTTER_IS_SCORE (score)); g_return_val_if_fail (CLUTTER_IS_SCORE (score), 0);
g_return_if_fail (id != NULL); g_return_val_if_fail (parent == NULL || CLUTTER_IS_TIMELINE (parent), 0);
g_return_if_fail (parent == NULL || CLUTTER_IS_TIMELINE (parent)); g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0);
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
priv = score->priv; priv = score->priv;
if (!parent) if (!parent)
{ {
ClutterScoreEntry *entry;
entry = g_slice_new (ClutterScoreEntry); entry = g_slice_new (ClutterScoreEntry);
entry->type = SCORE_ENTRY_APPEND;
entry->timeline = g_object_ref (timeline); entry->timeline = g_object_ref (timeline);
entry->parent = NULL; entry->parent = NULL;
entry->id = g_strdup (id); entry->id = priv->last_id;
entry->marker_id = 0; entry->marker_id = 0;
entry->score = score; entry->score = score;
@ -904,64 +899,69 @@ clutter_score_append (ClutterScore *score,
else else
{ {
GNode *node; GNode *node;
ClutterScoreEntry *entry;
node = find_entry_by_timeline (score, parent); node = find_entry_by_timeline (score, parent);
if (G_UNLIKELY (!node)) if (G_UNLIKELY (!node))
{ {
g_warning ("Unable to find the parent timeline inside the score."); g_warning ("Unable to find the parent timeline inside the score.");
return; return 0;
} }
entry = g_slice_new (ClutterScoreEntry); entry = g_slice_new (ClutterScoreEntry);
entry->type = SCORE_ENTRY_APPEND;
entry->timeline = g_object_ref (timeline); entry->timeline = g_object_ref (timeline);
entry->parent = parent; entry->parent = parent;
entry->id = g_strdup (id); entry->id = priv->last_id;
entry->marker_id = 0; entry->marker_id = 0;
entry->score = score; entry->score = score;
entry->node = g_node_append_data (node, entry); entry->node = g_node_append_data (node, entry);
} }
priv->last_id += 1;
return entry->id;
} }
/** /**
* clutter_score_append_at_time: * clutter_score_append_at_marker:
* @score: a #ClutterScore * @score: a #ClutterScore
* @id: a unique string identifying the timeline
* @parent: the parent #ClutterTimeline * @parent: the parent #ClutterTimeline
* @msecs: the time on @parent where the new timeline should * @marker_name: the name of the marker to use
* be appended, in milliseconds
* @timeline: the #ClutterTimeline to append * @timeline: the #ClutterTimeline to append
* *
* Appends @timeline at the given position on the @parent timeline, * Appends @timeline at the given @marker_name on the @parent
* expressed in milliseconds. * #ClutterTimeline.
*
* 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 * If you want to append @timeline at the end of @parent, use
* clutter_score_append(). * clutter_score_append().
* *
* Return value: the id of the #ClutterTimeline inside the score, or
* 0 on failure. The returned id can be used with clutter_score_remove()
* or clutter_score_get_timeline().
*
* Since: 0.8 * Since: 0.8
*/ */
void guint
clutter_score_append_at_time (ClutterScore *score, clutter_score_append_at_marker (ClutterScore *score,
const gchar *id, ClutterTimeline *parent,
ClutterTimeline *parent, const gchar *marker_name,
guint msecs, ClutterTimeline *timeline)
ClutterTimeline *timeline)
{ {
ClutterScorePrivate *priv; ClutterScorePrivate *priv;
GNode *node; GNode *node;
ClutterScoreEntry *entry; ClutterScoreEntry *entry;
gchar *marker_reached_signal; gchar *marker_reached_signal;
g_return_if_fail (CLUTTER_IS_SCORE (score)); g_return_val_if_fail (CLUTTER_IS_SCORE (score), 0);
g_return_if_fail (id != NULL); g_return_val_if_fail (CLUTTER_IS_TIMELINE (parent), 0);
g_return_if_fail (CLUTTER_IS_TIMELINE (parent)); g_return_val_if_fail (marker_name != NULL, 0);
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline)); g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), 0);
if (!clutter_timeline_has_marker (parent, marker_name))
{
g_warning ("The parent timeline has no marker `%s'", marker_name);
return 0;
}
priv = score->priv; priv = score->priv;
@ -969,22 +969,17 @@ clutter_score_append_at_time (ClutterScore *score,
if (G_UNLIKELY (!node)) if (G_UNLIKELY (!node))
{ {
g_warning ("Unable to find the parent timeline inside the score."); g_warning ("Unable to find the parent timeline inside the score.");
return; return 0;
} }
entry = g_slice_new (ClutterScoreEntry); entry = g_slice_new (ClutterScoreEntry);
entry->type = SCORE_ENTRY_TIME;
entry->timeline = g_object_ref (timeline); entry->timeline = g_object_ref (timeline);
entry->parent = parent; entry->parent = parent;
entry->msecs = msecs; entry->marker = g_strdup (marker_name);
entry->id = g_strdup (id); entry->id = priv->last_id;
entry->score = score; entry->score = score;
clutter_timeline_add_marker_at_time (entry->parent, marker_reached_signal = g_strdup_printf ("marker-reached::%s", marker_name);
entry->id,
entry->msecs);
marker_reached_signal = g_strdup_printf ("marker-reached::%s", entry->id);
entry->marker_id = g_signal_connect (entry->parent, entry->marker_id = g_signal_connect (entry->parent,
marker_reached_signal, marker_reached_signal,
G_CALLBACK (on_timeline_marker), G_CALLBACK (on_timeline_marker),
@ -993,76 +988,10 @@ clutter_score_append_at_time (ClutterScore *score,
entry->node = g_node_append_data (node, entry); entry->node = g_node_append_data (node, entry);
g_free (marker_reached_signal); g_free (marker_reached_signal);
}
/** priv->last_id += 1;
* 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)); return entry->id;
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);
} }
/** /**
@ -1074,11 +1003,11 @@ clutter_score_append_at_frame (ClutterScore *score,
* the timeline has other timelines attached to it, those are removed * the timeline has other timelines attached to it, those are removed
* as well. * as well.
* *
* Since: 0.8 * Since: 0.6
*/ */
void void
clutter_score_remove (ClutterScore *score, clutter_score_remove (ClutterScore *score,
const gchar *id) guint id)
{ {
ClutterScorePrivate *priv; ClutterScorePrivate *priv;
TraverseClosure closure; TraverseClosure closure;
@ -1140,11 +1069,11 @@ clutter_score_remove_all (ClutterScore *score)
* Return value: the requested timeline, or %NULL. This function does * Return value: the requested timeline, or %NULL. This function does
* not increase the reference count on the returned #ClutterTimeline * not increase the reference count on the returned #ClutterTimeline
* *
* Since: 0.8 * Since: 0.6
*/ */
ClutterTimeline * ClutterTimeline *
clutter_score_get_timeline (ClutterScore *score, clutter_score_get_timeline (ClutterScore *score,
const gchar *id) guint id)
{ {
GNode *node; GNode *node;
ClutterScoreEntry *entry; ClutterScoreEntry *entry;

View File

@ -77,36 +77,29 @@ GType clutter_score_get_type (void) G_GNUC_CONST;
ClutterScore * clutter_score_new (void); ClutterScore * clutter_score_new (void);
void clutter_score_set_loop (ClutterScore *score, void clutter_score_set_loop (ClutterScore *score,
gboolean loop); gboolean loop);
gboolean clutter_score_get_loop (ClutterScore *score); gboolean clutter_score_get_loop (ClutterScore *score);
void clutter_score_append_at_time (ClutterScore *score, guint clutter_score_append (ClutterScore *score,
const gchar *id, ClutterTimeline *parent,
ClutterTimeline *parent, ClutterTimeline *timeline);
guint msecs, guint clutter_score_append_at_marker (ClutterScore *score,
ClutterTimeline *timeline); ClutterTimeline *parent,
void clutter_score_append_at_frame (ClutterScore *score, const gchar *marker_name,
const gchar *id, ClutterTimeline *timeline);
ClutterTimeline *parent, void clutter_score_remove (ClutterScore *score,
guint frame, guint id);
ClutterTimeline *timeline); void clutter_score_remove_all (ClutterScore *score);
void clutter_score_append (ClutterScore *score, ClutterTimeline *clutter_score_get_timeline (ClutterScore *score,
const gchar *id, guint id);
ClutterTimeline *parent, GSList * clutter_score_list_timelines (ClutterScore *score);
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_start (ClutterScore *score);
void clutter_score_stop (ClutterScore *score); void clutter_score_stop (ClutterScore *score);
void clutter_score_pause (ClutterScore *score); void clutter_score_pause (ClutterScore *score);
void clutter_score_rewind (ClutterScore *score); void clutter_score_rewind (ClutterScore *score);
gboolean clutter_score_is_playing (ClutterScore *score); gboolean clutter_score_is_playing (ClutterScore *score);
G_END_DECLS G_END_DECLS

View File

@ -1650,3 +1650,25 @@ clutter_timeline_remove_marker (ClutterTimeline *timeline,
/* this will take care of freeing the marker as well */ /* this will take care of freeing the marker as well */
g_hash_table_remove (priv->markers_by_name, marker_name); g_hash_table_remove (priv->markers_by_name, marker_name);
} }
/**
* clutter_timeline_has_marker:
* @timeline: a #ClutterTimeline
* @marker_name: the name of the marker
*
* Checks whether @timeline has a marker set with the given name.
*
* Return value: %TRUE if the marker was found
*
* Since: 0.8
*/
gboolean
clutter_timeline_has_marker (ClutterTimeline *timeline,
const gchar *marker_name)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE);
g_return_val_if_fail (marker_name != NULL, FALSE);
return NULL != g_hash_table_lookup (timeline->priv->markers_by_name,
marker_name);
}

View File

@ -154,6 +154,8 @@ void clutter_timeline_remove_marker (ClutterTimeline *timeli
gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline, gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline,
gint frame_num, gint frame_num,
guint *n_markers) G_GNUC_MALLOC; guint *n_markers) G_GNUC_MALLOC;
gboolean clutter_timeline_has_marker (ClutterTimeline *timeline,
const gchar *marker_name);
void clutter_timeline_advance_to_marker (ClutterTimeline *timeline, void clutter_timeline_advance_to_marker (ClutterTimeline *timeline,
const gchar *marker_name); const gchar *marker_name);

View File

@ -1,3 +1,7 @@
2008-03-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter-section.txt: Update after API change in ClutterScore.
2008-03-18 Emmanuele Bassi <ebassi@openedhand.com> 2008-03-18 Emmanuele Bassi <ebassi@openedhand.com>
* clutter-section.txt: Add new score API. * clutter-section.txt: Add new score API.

View File

@ -1286,8 +1286,7 @@ clutter_score_get_loop
<SUBSECTION> <SUBSECTION>
clutter_score_append clutter_score_append
clutter_score_append_at_frame clutter_score_append_at_marker
clutter_score_append_at_time
clutter_score_remove clutter_score_remove
clutter_score_remove_all clutter_score_remove_all
clutter_score_get_timeline clutter_score_get_timeline

View File

@ -53,6 +53,7 @@ main (int argc, char **argv)
g_free); g_free);
timeline_2 = clutter_timeline_new_for_duration (1000); timeline_2 = clutter_timeline_new_for_duration (1000);
clutter_timeline_add_marker_at_time (timeline_2, "foo", 500);
g_object_set_data_full (G_OBJECT (timeline_2), g_object_set_data_full (G_OBJECT (timeline_2),
"timeline-name", g_strdup ("Timeline 2"), "timeline-name", g_strdup ("Timeline 2"),
g_free); g_free);
@ -83,12 +84,12 @@ main (int argc, char **argv)
G_CALLBACK (clutter_main_quit), G_CALLBACK (clutter_main_quit),
NULL); NULL);
clutter_score_append (score, "line-0", NULL, timeline_1); clutter_score_append (score, NULL, timeline_1);
clutter_score_append (score, "line-1", timeline_1, timeline_2); clutter_score_append (score, timeline_1, timeline_2);
clutter_score_append (score, "line-2", timeline_1, timeline_3); clutter_score_append (score, timeline_1, timeline_3);
clutter_score_append (score, "line-3", timeline_3, timeline_4); clutter_score_append (score, timeline_3, timeline_4);
clutter_score_append_at_time (score, "line-4", timeline_2, 500, timeline_5); clutter_score_append_at_marker (score, timeline_2, "foo", timeline_5);
timelines = clutter_score_list_timelines (score); timelines = clutter_score_list_timelines (score);
g_assert (5 == g_slist_length (timelines)); g_assert (5 == g_slist_length (timelines));