mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
2007-12-04 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-score.[ch]: Reimplement ClutterScore using a N-ary tree to store the timelines. Remove clutter_score_add(): the same functionality can be achieved by passing a NULL parent to clutter_score_append(). * tests/test-score.c: Update ClutterScore test unit, and add debug printouts.
This commit is contained in:
parent
094c5f77b8
commit
51a0d5a80f
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2007-12-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
* clutter/clutter-score.[ch]: Reimplement ClutterScore using
|
||||||
|
a N-ary tree to store the timelines. Remove clutter_score_add():
|
||||||
|
the same functionality can be achieved by passing a NULL
|
||||||
|
parent to clutter_score_append().
|
||||||
|
|
||||||
|
* tests/test-score.c: Update ClutterScore test unit, and add
|
||||||
|
debug printouts.
|
||||||
|
|
||||||
2007-12-04 Øyvind Kolås <pippin@o-hand.com>
|
2007-12-04 Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
|
||||||
* clutter/clutter-shader.c: (bind_glsl_shader): use gchar instead of
|
* clutter/clutter-shader.c: (bind_glsl_shader): use gchar instead of
|
||||||
|
@ -427,12 +427,14 @@ clutter_rectangle_set_color
|
|||||||
clutter_redraw
|
clutter_redraw
|
||||||
clutter_rotate_axis_get_type
|
clutter_rotate_axis_get_type
|
||||||
clutter_rotate_direction_get_type
|
clutter_rotate_direction_get_type
|
||||||
clutter_score_add
|
|
||||||
clutter_score_append
|
clutter_score_append
|
||||||
clutter_score_get_loop
|
clutter_score_get_loop
|
||||||
|
clutter_score_get_timeline
|
||||||
clutter_score_get_type
|
clutter_score_get_type
|
||||||
clutter_score_is_playing
|
clutter_score_is_playing
|
||||||
|
clutter_score_list_timelines
|
||||||
clutter_score_new
|
clutter_score_new
|
||||||
|
clutter_score_remove
|
||||||
clutter_score_remove_all
|
clutter_score_remove_all
|
||||||
clutter_score_rewind
|
clutter_score_rewind
|
||||||
clutter_score_start
|
clutter_score_start
|
||||||
|
@ -23,26 +23,6 @@
|
|||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* IDEAS:
|
|
||||||
* API;
|
|
||||||
* - add()
|
|
||||||
* + an new timeline to beginning of score
|
|
||||||
* - append (timeline_existing, timeline_new, delay)
|
|
||||||
* + appends a new timeline to an existing one
|
|
||||||
*
|
|
||||||
* ScoreEntry
|
|
||||||
* {
|
|
||||||
* Timeline *base;
|
|
||||||
* GList *next_timelines; - to start on completion of base,
|
|
||||||
* (points to score entries)
|
|
||||||
* Callback id;
|
|
||||||
* delay
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* start()/stop(),remove(),remove_all() ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:clutter-score
|
* SECTION:clutter-score
|
||||||
* @short_description: Sequencing multiple #ClutterTimelines in order
|
* @short_description: Sequencing multiple #ClutterTimelines in order
|
||||||
@ -62,34 +42,48 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterScore, clutter_score, G_TYPE_OBJECT);
|
typedef struct _ClutterScoreEntry ClutterScoreEntry;
|
||||||
|
|
||||||
typedef struct ClutterScoreEntry
|
struct _ClutterScoreEntry
|
||||||
{
|
{
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
gulong handler_id;
|
guint id;
|
||||||
GSList *child_entries;
|
|
||||||
ClutterScore *score;
|
/* signal handler id */
|
||||||
}
|
gulong completed_id;
|
||||||
ClutterScoreEntry;
|
|
||||||
|
ClutterScore *score;
|
||||||
|
|
||||||
|
/* pointer back to the tree structure */
|
||||||
|
GNode *node;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CLUTTER_SCORE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_SCORE, ClutterScorePrivate))
|
||||||
|
|
||||||
struct _ClutterScorePrivate
|
struct _ClutterScorePrivate
|
||||||
{
|
{
|
||||||
GSList *entries;
|
GNode *root;
|
||||||
GHashTable *running_timelines;
|
|
||||||
guint paused :1;
|
GHashTable *running_timelines;
|
||||||
guint loop : 1;
|
|
||||||
|
guint last_id;
|
||||||
|
|
||||||
|
guint is_paused : 1;
|
||||||
|
guint loop : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
PROP_LOOP
|
PROP_LOOP
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NEW_TIMELINE,
|
TIMELINE_STARTED,
|
||||||
|
TIMELINE_COMPLETED,
|
||||||
|
|
||||||
STARTED,
|
STARTED,
|
||||||
PAUSED,
|
PAUSED,
|
||||||
COMPLETED,
|
COMPLETED,
|
||||||
@ -97,23 +91,19 @@ enum
|
|||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int score_signals[LAST_SIGNAL] = { 0 };
|
G_DEFINE_TYPE (ClutterScore, clutter_score, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void start_entry (ClutterScoreEntry *entry);
|
static int score_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
/* Object */
|
/* Object */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_score_set_property (GObject *object,
|
clutter_score_set_property (GObject *gobject,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
ClutterScore *score;
|
ClutterScorePrivate *priv = CLUTTER_SCORE_GET_PRIVATE (gobject);
|
||||||
ClutterScorePrivate *priv;
|
|
||||||
|
|
||||||
score = CLUTTER_SCORE(object);
|
|
||||||
priv = score->priv;
|
|
||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
@ -121,22 +111,18 @@ clutter_score_set_property (GObject *object,
|
|||||||
priv->loop = g_value_get_boolean (value);
|
priv->loop = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_score_get_property (GObject *object,
|
clutter_score_get_property (GObject *gobject,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
ClutterScore *score;
|
ClutterScorePrivate *priv = CLUTTER_SCORE_GET_PRIVATE (gobject);
|
||||||
ClutterScorePrivate *priv;
|
|
||||||
|
|
||||||
score = CLUTTER_SCORE(object);
|
|
||||||
priv = score->priv;
|
|
||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
@ -144,7 +130,7 @@ clutter_score_get_property (GObject *object,
|
|||||||
g_value_set_boolean (value, priv->loop);
|
g_value_set_boolean (value, priv->loop);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +140,9 @@ clutter_score_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
ClutterScorePrivate *priv = CLUTTER_SCORE (object)->priv;
|
ClutterScorePrivate *priv = CLUTTER_SCORE (object)->priv;
|
||||||
|
|
||||||
g_hash_table_destroy (priv->running_timelines);
|
if (priv->running_timelines)
|
||||||
|
g_hash_table_destroy (priv->running_timelines);
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_score_parent_class)->finalize (object);
|
G_OBJECT_CLASS (clutter_score_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,70 +161,152 @@ clutter_score_dispose (GObject *object)
|
|||||||
static void
|
static void
|
||||||
clutter_score_class_init (ClutterScoreClass *klass)
|
clutter_score_class_init (ClutterScoreClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class;
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class = (GObjectClass*) klass;
|
gobject_class->set_property = clutter_score_set_property;
|
||||||
|
gobject_class->get_property = clutter_score_get_property;
|
||||||
object_class->set_property = clutter_score_set_property;
|
gobject_class->finalize = clutter_score_finalize;
|
||||||
object_class->get_property = clutter_score_get_property;
|
gobject_class->dispose = clutter_score_dispose;
|
||||||
object_class->finalize = clutter_score_finalize;
|
|
||||||
object_class->dispose = clutter_score_dispose;
|
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (ClutterScorePrivate));
|
g_type_class_add_private (klass, sizeof (ClutterScorePrivate));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterScore:loop:
|
||||||
|
*
|
||||||
|
* Whether the #ClutterScore should restart once finished.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_LOOP,
|
||||||
|
g_param_spec_boolean ("loop",
|
||||||
|
"Loop",
|
||||||
|
"Whether the score should restart once finished",
|
||||||
|
FALSE,
|
||||||
|
CLUTTER_PARAM_READWRITE));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ClutterScore::new-timeline:
|
* ClutterScore::timeline-started:
|
||||||
* @score: the score which received the signal
|
* @score: the score which received the signal
|
||||||
* @timeline: the current timeline
|
* @timeline: the current timeline
|
||||||
*
|
*
|
||||||
* The ::new-timeline signal is emitted each time a new timeline in the
|
* The ::timeline-started signal is emitted each time a new timeline
|
||||||
* score is reached.
|
* inside a #ClutterScore starts playing.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
score_signals[NEW_TIMELINE] =
|
score_signals[TIMELINE_STARTED] =
|
||||||
g_signal_new ("new-timeline",
|
g_signal_new ("timeline-started",
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (ClutterScoreClass, new_timeline),
|
G_STRUCT_OFFSET (ClutterScoreClass, timeline_started),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
clutter_marshal_VOID__OBJECT,
|
clutter_marshal_VOID__OBJECT,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
1, CLUTTER_TYPE_TIMELINE);
|
1, CLUTTER_TYPE_TIMELINE);
|
||||||
|
/**
|
||||||
|
* ClutterScore::timeline-completed:
|
||||||
|
* @score: the score which received the signal
|
||||||
|
* @timeline: the completed timeline
|
||||||
|
*
|
||||||
|
* The ::timeline-completed signal is emitted each time a timeline
|
||||||
|
* inside a #ClutterScore terminates.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
score_signals[TIMELINE_COMPLETED] =
|
||||||
|
g_signal_new ("timeline-completed",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterScoreClass, timeline_completed),
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
CLUTTER_TYPE_TIMELINE);
|
||||||
|
/**
|
||||||
|
* ClutterScore::completed:
|
||||||
|
* @score: the score which received the signal
|
||||||
|
*
|
||||||
|
* The ::completed signal is emitted each time a #ClutterScore terminates.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
score_signals[COMPLETED] =
|
score_signals[COMPLETED] =
|
||||||
g_signal_new ("completed",
|
g_signal_new ("completed",
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (ClutterScoreClass, completed),
|
G_STRUCT_OFFSET (ClutterScoreClass, completed),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
clutter_marshal_VOID__VOID,
|
clutter_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
/**
|
||||||
|
* ClutterScore::started:
|
||||||
|
* @score: the score which received the signal
|
||||||
|
*
|
||||||
|
* The ::started signal is emitted each time a #ClutterScore starts playing.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
score_signals[STARTED] =
|
score_signals[STARTED] =
|
||||||
g_signal_new ("started",
|
g_signal_new ("started",
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (ClutterScoreClass, started),
|
G_STRUCT_OFFSET (ClutterScoreClass, started),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
clutter_marshal_VOID__VOID,
|
clutter_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
/**
|
||||||
|
* ClutterScore::paused:
|
||||||
|
* @score: the score which received the signal
|
||||||
|
*
|
||||||
|
* The ::paused signal is emitted each time a #ClutterScore
|
||||||
|
* is paused.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
score_signals[PAUSED] =
|
score_signals[PAUSED] =
|
||||||
g_signal_new ("paused",
|
g_signal_new ("paused",
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
G_STRUCT_OFFSET (ClutterScoreClass, paused),
|
G_STRUCT_OFFSET (ClutterScoreClass, paused),
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
clutter_marshal_VOID__VOID,
|
clutter_marshal_VOID__VOID,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_score_init (ClutterScore *self)
|
clutter_score_init (ClutterScore *self)
|
||||||
{
|
{
|
||||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
|
ClutterScorePrivate *priv;
|
||||||
CLUTTER_TYPE_SCORE,
|
|
||||||
ClutterScorePrivate);
|
|
||||||
|
|
||||||
self->priv->running_timelines = g_hash_table_new(NULL, NULL);
|
self->priv = priv = CLUTTER_SCORE_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
/* sentinel */
|
||||||
|
priv->root = g_node_new (NULL);
|
||||||
|
|
||||||
|
priv->running_timelines = NULL;
|
||||||
|
|
||||||
|
priv->is_paused = FALSE;
|
||||||
|
priv->loop = FALSE;
|
||||||
|
|
||||||
|
priv->last_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_score_new:
|
||||||
|
*
|
||||||
|
* Creates a new #ClutterScore. A #ClutterScore is an object that can
|
||||||
|
* hold multiple #ClutterTimeline<!-- -->s in a sequential order.
|
||||||
|
*
|
||||||
|
* Return value: the newly created #ClutterScore. Use g_object_unref()
|
||||||
|
* when done.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
ClutterScore *
|
||||||
|
clutter_score_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (CLUTTER_TYPE_SCORE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,76 +352,108 @@ clutter_score_get_loop (ClutterScore *score)
|
|||||||
*
|
*
|
||||||
* Query state of a #ClutterScore instance.
|
* Query state of a #ClutterScore instance.
|
||||||
*
|
*
|
||||||
* Return Value: TRUE if score is currently playing, FALSE if not.
|
* Return Value: %TRUE if score is currently playing
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
clutter_score_is_playing (ClutterScore *score)
|
clutter_score_is_playing (ClutterScore *score)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE);
|
g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE);
|
||||||
|
|
||||||
/* FIXME: paused state currently counts as playing */
|
if (score->priv->is_paused)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return !!g_hash_table_size (score->priv->running_timelines);
|
return (g_hash_table_size (score->priv->running_timelines) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* forward declaration */
|
||||||
|
static void start_entry (ClutterScoreEntry *entry);
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_children_entries (GNode *node,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterScoreEntry *entry = node->data;
|
||||||
|
|
||||||
|
start_entry (entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_timeline_finish (ClutterTimeline *timeline,
|
on_timeline_finish (ClutterTimeline *timeline,
|
||||||
ClutterScoreEntry *entry)
|
ClutterScoreEntry *entry)
|
||||||
{
|
{
|
||||||
GSList *item;
|
ClutterScorePrivate *priv = entry->score->priv;
|
||||||
|
|
||||||
g_hash_table_remove (entry->score->priv->running_timelines,
|
g_hash_table_remove (priv->running_timelines,
|
||||||
GINT_TO_POINTER(entry->handler_id));
|
GINT_TO_POINTER (entry->id));
|
||||||
|
|
||||||
g_signal_handler_disconnect (timeline, entry->handler_id);
|
g_signal_handler_disconnect (timeline, entry->completed_id);
|
||||||
|
entry->completed_id = 0;
|
||||||
|
|
||||||
CLUTTER_NOTE (SCHEDULER,
|
CLUTTER_NOTE (SCHEDULER, "timeline [%p] (%d) completed",
|
||||||
"completed %p %li\n",
|
entry->timeline,
|
||||||
entry->timeline, entry->handler_id);
|
entry->id);
|
||||||
|
|
||||||
for (item = entry->child_entries; item != NULL; item = item->next)
|
g_signal_emit (entry->score, score_signals[TIMELINE_COMPLETED], 0,
|
||||||
|
entry->timeline);
|
||||||
|
|
||||||
|
/* start every child */
|
||||||
|
if (entry->node->children)
|
||||||
{
|
{
|
||||||
ClutterScoreEntry *child_entry = item->data;
|
g_node_children_foreach (entry->node,
|
||||||
start_entry (child_entry);
|
G_TRAVERSE_ALL,
|
||||||
|
start_children_entries,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clutter_score_is_playing (entry->score) == FALSE)
|
/* score has finished - fire 'completed' signal */
|
||||||
|
if (g_hash_table_size (priv->running_timelines) == 0)
|
||||||
{
|
{
|
||||||
/* Score has finished - fire 'completed' signal */
|
CLUTTER_NOTE (SCHEDULER, "looks like we finished");
|
||||||
/* Also check if looped etc */
|
|
||||||
CLUTTER_NOTE (SCHEDULER, "looks like we finished\n");
|
|
||||||
|
|
||||||
g_signal_emit (entry->score, score_signals[COMPLETED], 0);
|
g_signal_emit (entry->score, score_signals[COMPLETED], 0);
|
||||||
|
|
||||||
|
clutter_score_stop (entry->score);
|
||||||
|
|
||||||
|
if (priv->loop)
|
||||||
|
clutter_score_start (entry->score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_entry (ClutterScoreEntry *entry)
|
start_entry (ClutterScoreEntry *entry)
|
||||||
{
|
{
|
||||||
entry->handler_id = g_signal_connect (entry->timeline,
|
ClutterScorePrivate *priv = entry->score->priv;
|
||||||
"completed",
|
|
||||||
G_CALLBACK (on_timeline_finish),
|
|
||||||
entry);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (SCHEDULER,
|
entry->completed_id =
|
||||||
"started %p %li\n", entry->timeline, entry->handler_id);
|
g_signal_connect (entry->timeline,
|
||||||
|
"completed", G_CALLBACK (on_timeline_finish),
|
||||||
|
entry);
|
||||||
|
|
||||||
g_hash_table_insert (entry->score->priv->running_timelines,
|
CLUTTER_NOTE (SCHEDULER, "timeline [%p] (%d) started",
|
||||||
GINT_TO_POINTER(entry->handler_id),
|
entry->timeline,
|
||||||
|
entry->id);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (priv->running_timelines == NULL))
|
||||||
|
priv->running_timelines = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
|
g_hash_table_insert (priv->running_timelines,
|
||||||
|
GINT_TO_POINTER (entry->id),
|
||||||
entry);
|
entry);
|
||||||
|
|
||||||
clutter_timeline_start (entry->timeline);
|
clutter_timeline_start (entry->timeline);
|
||||||
|
|
||||||
g_signal_emit (entry->score, score_signals[NEW_TIMELINE],
|
g_signal_emit (entry->score, score_signals[TIMELINE_STARTED], 0,
|
||||||
0, entry->timeline);
|
entry->timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
on_foreach_running_timeline_start (gpointer key,
|
foreach_running_timeline_start (gpointer key,
|
||||||
gpointer value,
|
gpointer value,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
clutter_timeline_start (CLUTTER_TIMELINE(value));
|
ClutterScoreEntry *entry = value;
|
||||||
|
|
||||||
|
clutter_timeline_start (entry->timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -365,36 +467,37 @@ on_foreach_running_timeline_start (gpointer key,
|
|||||||
void
|
void
|
||||||
clutter_score_start (ClutterScore *score)
|
clutter_score_start (ClutterScore *score)
|
||||||
{
|
{
|
||||||
GSList *item;
|
|
||||||
ClutterScorePrivate *priv;
|
ClutterScorePrivate *priv;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_SCORE (score));
|
g_return_if_fail (CLUTTER_IS_SCORE (score));
|
||||||
|
|
||||||
priv = score->priv;
|
priv = score->priv;
|
||||||
|
|
||||||
if (priv->paused)
|
if (priv->is_paused)
|
||||||
{
|
{
|
||||||
g_hash_table_foreach (priv->running_timelines,
|
g_hash_table_foreach (priv->running_timelines,
|
||||||
(GHFunc)on_foreach_running_timeline_start,
|
foreach_running_timeline_start,
|
||||||
NULL);
|
NULL);
|
||||||
priv->paused = 0;
|
priv->is_paused = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (item = priv->entries; item != NULL; item = item->next)
|
g_node_children_foreach (priv->root,
|
||||||
{
|
G_TRAVERSE_ALL,
|
||||||
ClutterScoreEntry *entry = item->data;
|
start_children_entries,
|
||||||
start_entry (entry);
|
NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
on_foreach_running_timeline_stop (gpointer key,
|
foreach_running_timeline_stop (gpointer key,
|
||||||
gpointer value,
|
gpointer value,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
clutter_timeline_stop (((ClutterScoreEntry*)value)->timeline);
|
ClutterScoreEntry *entry = value;
|
||||||
|
|
||||||
|
clutter_timeline_stop (entry->timeline);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,8 +518,10 @@ clutter_score_stop (ClutterScore *score)
|
|||||||
priv = score->priv;
|
priv = score->priv;
|
||||||
|
|
||||||
g_hash_table_foreach_remove (priv->running_timelines,
|
g_hash_table_foreach_remove (priv->running_timelines,
|
||||||
(GHRFunc)on_foreach_running_timeline_stop,
|
foreach_running_timeline_stop,
|
||||||
NULL);
|
NULL);
|
||||||
|
g_hash_table_destroy (priv->running_timelines);
|
||||||
|
priv->running_timelines = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -440,12 +545,14 @@ clutter_score_rewind (ClutterScore *score)
|
|||||||
clutter_score_start (score);
|
clutter_score_start (score);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
on_foreach_running_timeline_pause (gpointer key,
|
foreach_running_timeline_pause (gpointer key,
|
||||||
gpointer value,
|
gpointer value,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
clutter_timeline_pause (((ClutterScoreEntry*)value)->timeline);
|
ClutterScoreEntry *entry = value;
|
||||||
|
|
||||||
|
clutter_timeline_pause (entry->timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -457,131 +564,278 @@ clutter_score_pause (ClutterScore *score)
|
|||||||
|
|
||||||
priv = score->priv;
|
priv = score->priv;
|
||||||
|
|
||||||
if (priv->paused || !clutter_score_is_playing (score))
|
if (!clutter_score_is_playing (score))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_hash_table_foreach (priv->running_timelines,
|
g_hash_table_foreach (priv->running_timelines,
|
||||||
(GHFunc)on_foreach_running_timeline_pause,
|
foreach_running_timeline_pause,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
priv->paused = 1;
|
priv->is_paused = TRUE;
|
||||||
|
|
||||||
g_signal_emit (score, score_signals[PAUSED], 0);
|
g_signal_emit (score, score_signals[PAUSED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterScoreEntry*
|
typedef enum {
|
||||||
find_entry (GSList *list, ClutterTimeline *timeline)
|
FIND_BY_TIMELINE,
|
||||||
|
FIND_BY_ID,
|
||||||
|
REMOVE_BY_ID,
|
||||||
|
LIST_TIMELINES
|
||||||
|
} TraverseAction;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TraverseAction action;
|
||||||
|
|
||||||
|
ClutterScore *score;
|
||||||
|
|
||||||
|
union {
|
||||||
|
ClutterTimeline *timeline;
|
||||||
|
guint id;
|
||||||
|
ClutterScoreEntry *entry;
|
||||||
|
} d;
|
||||||
|
|
||||||
|
gpointer result;
|
||||||
|
} TraverseClosure;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
destroy_entry (GNode *node,
|
||||||
|
G_GNUC_UNUSED gpointer data)
|
||||||
{
|
{
|
||||||
GSList *item;
|
ClutterScoreEntry *entry = node->data;
|
||||||
ClutterScoreEntry *res = NULL;
|
|
||||||
|
|
||||||
if (list == NULL)
|
if (G_LIKELY (entry != NULL))
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (item = list; item != NULL && res == NULL; item = item->next)
|
|
||||||
{
|
{
|
||||||
ClutterScoreEntry *entry = item->data;
|
if (entry->completed_id)
|
||||||
|
g_signal_handler_disconnect (entry->timeline, entry->completed_id);
|
||||||
|
|
||||||
g_assert (entry != NULL);
|
g_object_unref (entry->timeline);
|
||||||
|
g_slice_free (ClutterScoreEntry, entry);
|
||||||
|
|
||||||
if (entry->timeline == timeline)
|
node->data = NULL;
|
||||||
return entry;
|
|
||||||
|
|
||||||
if (entry->child_entries)
|
|
||||||
res = find_entry (entry->child_entries, timeline);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
/* continue */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
retval = TRUE;
|
||||||
|
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,
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_score_append:
|
* clutter_score_append:
|
||||||
* @score: A #ClutterScore
|
* @score: a #ClutterScore
|
||||||
* @timeline_existing: A #ClutterTimeline in the score
|
* @parent: a #ClutterTimeline in the score or %NULL
|
||||||
* @timeline_new: A new #ClutterTimeline to start when #timeline_existing has
|
* @timeline: a #ClutterTimeline
|
||||||
* completed,
|
|
||||||
*
|
*
|
||||||
* Appends a new timeline to an one existing in the score.
|
* Appends a timeline to another one existing in the score; the newly
|
||||||
|
* appended timeline will be started when @parent is complete.
|
||||||
*
|
*
|
||||||
|
* If @parent is %NULL, the new #ClutterTimeline will be started when
|
||||||
|
* clutter_score_start() is called.
|
||||||
|
*
|
||||||
|
* Return value: the id of the newly added timeline, to be used with
|
||||||
|
* clutter_score_get_timeline() and clutter_score_remove().
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
void
|
guint
|
||||||
clutter_score_append (ClutterScore *score,
|
clutter_score_append (ClutterScore *score,
|
||||||
ClutterTimeline *timeline_existing,
|
ClutterTimeline *parent,
|
||||||
ClutterTimeline *timeline_new)
|
ClutterTimeline *timeline)
|
||||||
{
|
{
|
||||||
ClutterScorePrivate *priv;
|
ClutterScorePrivate *priv;
|
||||||
ClutterScoreEntry *entry, *entry_new;
|
|
||||||
|
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);
|
||||||
|
|
||||||
priv = score->priv;
|
priv = score->priv;
|
||||||
|
|
||||||
/* Appends a timeline to the end of another */
|
if (!parent)
|
||||||
if ((entry = find_entry (priv->entries, timeline_existing)) != NULL)
|
|
||||||
{
|
{
|
||||||
entry_new = g_new0(ClutterScoreEntry, 1);
|
ClutterScoreEntry *entry;
|
||||||
entry_new->timeline = g_object_ref (timeline_new);
|
|
||||||
entry_new->score = score;
|
|
||||||
|
|
||||||
entry->child_entries = g_slist_append (entry->child_entries, entry_new);
|
entry = g_slice_new (ClutterScoreEntry);
|
||||||
|
|
||||||
clutter_timeline_stop (timeline_new); /* stop it */
|
entry->timeline = g_object_ref (timeline);
|
||||||
|
entry->id = priv->last_id;
|
||||||
|
entry->completed_id = 0;
|
||||||
|
entry->score = score;
|
||||||
|
|
||||||
|
entry->node = g_node_append_data (priv->root, entry);
|
||||||
|
|
||||||
|
priv->last_id += 1;
|
||||||
|
|
||||||
|
return entry->id;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNode *node;
|
||||||
|
ClutterScoreEntry *entry;
|
||||||
|
|
||||||
|
node = find_entry_by_timeline (score, parent);
|
||||||
|
if (G_UNLIKELY (!node))
|
||||||
|
{
|
||||||
|
g_warning ("Unable to find the parent timeline inside the score.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = g_slice_new (ClutterScoreEntry);
|
||||||
|
entry->timeline = g_object_ref (timeline);
|
||||||
|
entry->id = priv->last_id;
|
||||||
|
entry->completed_id = 0;
|
||||||
|
entry->score = score;
|
||||||
|
|
||||||
|
entry->node = g_node_append_data (node, entry);
|
||||||
|
|
||||||
|
priv->last_id += 1;
|
||||||
|
|
||||||
|
return entry->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_score_add:
|
* clutter_score_remove:
|
||||||
* @score: A #ClutterScore
|
* @score: a #ClutterScore
|
||||||
* @timeline: A #ClutterTimeline
|
* @id: the id of the timeline to remove
|
||||||
*
|
*
|
||||||
* Adds a new initial timeline to start when the score is started.
|
* Removes the #ClutterTimeline with the given id inside @score. If
|
||||||
|
* the timeline has other timelines attached to it, those are removed
|
||||||
|
* as well.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_score_add (ClutterScore *score,
|
clutter_score_remove (ClutterScore *score,
|
||||||
ClutterTimeline *timeline)
|
guint id)
|
||||||
{
|
{
|
||||||
ClutterScorePrivate *priv;
|
ClutterScorePrivate *priv;
|
||||||
ClutterScoreEntry *entry;
|
TraverseClosure closure;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_SCORE (score));
|
||||||
|
g_return_if_fail (id > 0);
|
||||||
|
|
||||||
priv = score->priv;
|
priv = score->priv;
|
||||||
|
|
||||||
/* Added timelines are always started first */
|
closure.action = REMOVE_BY_ID;
|
||||||
entry = g_new0(ClutterScoreEntry, 1);
|
closure.score = score;
|
||||||
entry->timeline = g_object_ref (timeline);
|
closure.d.id = id;
|
||||||
entry->score = score;
|
closure.result = NULL;
|
||||||
score->priv->entries = g_slist_append (score->priv->entries, entry);
|
|
||||||
|
|
||||||
clutter_timeline_stop (timeline); /* stop it */
|
g_node_traverse (priv->root,
|
||||||
|
G_POST_ORDER,
|
||||||
CLUTTER_NOTE (SCHEDULER, "added timeline %p\n", entry->timeline);
|
G_TRAVERSE_ALL,
|
||||||
}
|
-1,
|
||||||
|
traverse_children, &closure);
|
||||||
static void
|
|
||||||
remove_entries (GSList *list)
|
|
||||||
{
|
|
||||||
GSList *item;
|
|
||||||
|
|
||||||
if (!list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (item = list; item != NULL; item = item->next)
|
|
||||||
{
|
|
||||||
ClutterScoreEntry *entry = item->data;
|
|
||||||
|
|
||||||
g_object_unref (entry->timeline);
|
|
||||||
|
|
||||||
if (entry->child_entries)
|
|
||||||
remove_entries (entry->child_entries);
|
|
||||||
|
|
||||||
g_slist_free (entry->child_entries);
|
|
||||||
g_free(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_remove (ClutterScore *score,
|
|
||||||
ClutterTimeline *timeline_parent,
|
|
||||||
ClutterTimeline *timeline)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
if (closure.result)
|
||||||
|
g_node_destroy (closure.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -595,21 +849,66 @@ clutter_score_remove (ClutterScore *score,
|
|||||||
void
|
void
|
||||||
clutter_score_remove_all (ClutterScore *score)
|
clutter_score_remove_all (ClutterScore *score)
|
||||||
{
|
{
|
||||||
|
ClutterScorePrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_SCORE (score));
|
||||||
|
|
||||||
|
/* this will take care of the running timelines */
|
||||||
clutter_score_stop (score);
|
clutter_score_stop (score);
|
||||||
remove_entries (score->priv->entries);
|
|
||||||
|
priv = score->priv;
|
||||||
|
|
||||||
|
g_node_traverse (priv->root,
|
||||||
|
G_POST_ORDER,
|
||||||
|
G_TRAVERSE_ALL,
|
||||||
|
-1,
|
||||||
|
destroy_entry, NULL);
|
||||||
|
g_node_destroy (priv->root);
|
||||||
|
|
||||||
|
/* sentinel */
|
||||||
|
priv->root = g_node_new (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ClutterTimeline *
|
||||||
* clutter_score_new:
|
clutter_score_get_timeline (ClutterScore *score,
|
||||||
*
|
guint id)
|
||||||
* Creates a new #ClutterScore.
|
|
||||||
*
|
|
||||||
* Return value: the newly created #ClutterScore
|
|
||||||
*
|
|
||||||
* Since: 0.6
|
|
||||||
*/
|
|
||||||
ClutterScore *
|
|
||||||
clutter_score_new (void)
|
|
||||||
{
|
{
|
||||||
return g_object_new (CLUTTER_TYPE_SCORE, NULL);
|
GNode *node;
|
||||||
|
ClutterScoreEntry *entry;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_SCORE (score), NULL);
|
||||||
|
g_return_val_if_fail (id > 0, NULL);
|
||||||
|
|
||||||
|
node = find_entry_by_id (score, id);
|
||||||
|
if (G_UNLIKELY (!node))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
entry = node->data;
|
||||||
|
|
||||||
|
return entry->timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSList *
|
||||||
|
clutter_score_list_timelines (ClutterScore *score)
|
||||||
|
{
|
||||||
|
ClutterScorePrivate *priv;
|
||||||
|
TraverseClosure closure;
|
||||||
|
GSList *retval;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_SCORE (score), NULL);
|
||||||
|
|
||||||
|
priv = score->priv;
|
||||||
|
|
||||||
|
closure.action = LIST_TIMELINES;
|
||||||
|
closure.result = NULL;
|
||||||
|
|
||||||
|
g_node_traverse (priv->root,
|
||||||
|
G_POST_ORDER,
|
||||||
|
G_TRAVERSE_ALL,
|
||||||
|
-1,
|
||||||
|
traverse_children, &closure);
|
||||||
|
|
||||||
|
retval = closure.result;
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -23,41 +23,24 @@
|
|||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _HAVE_CLUTTER_SCORE_H
|
#ifndef __CLUTTER_SCORE_H__
|
||||||
#define _HAVE_CLUTTER_SCORE_H
|
#define __CLUTTER_SCORE_H__
|
||||||
|
|
||||||
/* clutter-score.h */
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <clutter/clutter-timeline.h>
|
#include <clutter/clutter-timeline.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_SCORE clutter_score_get_type()
|
#define CLUTTER_TYPE_SCORE (clutter_score_get_type ())
|
||||||
|
|
||||||
#define CLUTTER_SCORE(obj) \
|
#define CLUTTER_SCORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCORE, ClutterScore))
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
#define CLUTTER_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCORE, ClutterScoreClass))
|
||||||
CLUTTER_TYPE_SCORE, ClutterScore))
|
#define CLUTTER_IS_SCORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCORE))
|
||||||
|
#define CLUTTER_IS_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCORE))
|
||||||
#define CLUTTER_SCORE_CLASS(klass) \
|
#define CLUTTER_SCORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCORE, ClutterScoreClass))
|
||||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
|
||||||
CLUTTER_TYPE_SCORE, ClutterScoreClass))
|
|
||||||
|
|
||||||
#define CLUTTER_IS_SCORE(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
|
||||||
CLUTTER_TYPE_SCORE))
|
|
||||||
|
|
||||||
#define CLUTTER_IS_SCORE_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
|
||||||
CLUTTER_TYPE_SCORE))
|
|
||||||
|
|
||||||
#define CLUTTER_SCORE_GET_CLASS(obj) \
|
|
||||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
|
||||||
CLUTTER_TYPE_SCORE, ClutterScoreClass))
|
|
||||||
|
|
||||||
typedef struct _ClutterScore ClutterScore;
|
typedef struct _ClutterScore ClutterScore;
|
||||||
typedef struct _ClutterScoreClass ClutterScoreClass;
|
|
||||||
typedef struct _ClutterScorePrivate ClutterScorePrivate;
|
typedef struct _ClutterScorePrivate ClutterScorePrivate;
|
||||||
|
typedef struct _ClutterScoreClass ClutterScoreClass;
|
||||||
|
|
||||||
struct _ClutterScore
|
struct _ClutterScore
|
||||||
{
|
{
|
||||||
@ -68,13 +51,21 @@ struct _ClutterScore
|
|||||||
|
|
||||||
struct _ClutterScoreClass
|
struct _ClutterScoreClass
|
||||||
{
|
{
|
||||||
|
/*< private >*/
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (*new_timeline) (ClutterScore *score, ClutterTimeline *timeline);
|
/*< public >*/
|
||||||
void (*started) (ClutterScore *score);
|
void (* timeline_started) (ClutterScore *score,
|
||||||
void (*completed) (ClutterScore *score);
|
ClutterTimeline *timeline);
|
||||||
void (*paused) (ClutterScore *score);
|
void (* timeline_completed) (ClutterScore *score,
|
||||||
|
ClutterTimeline *timeline);
|
||||||
|
|
||||||
|
void (* started) (ClutterScore *score);
|
||||||
|
void (* completed) (ClutterScore *score);
|
||||||
|
void (* paused) (ClutterScore *score);
|
||||||
|
|
||||||
|
/*< private >*/
|
||||||
|
/* padding for future expansion */
|
||||||
void (*_clutter_score_1) (void);
|
void (*_clutter_score_1) (void);
|
||||||
void (*_clutter_score_2) (void);
|
void (*_clutter_score_2) (void);
|
||||||
void (*_clutter_score_3) (void);
|
void (*_clutter_score_3) (void);
|
||||||
@ -84,48 +75,27 @@ struct _ClutterScoreClass
|
|||||||
|
|
||||||
GType clutter_score_get_type (void) G_GNUC_CONST;
|
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,
|
||||||
|
gboolean loop);
|
||||||
|
gboolean clutter_score_get_loop (ClutterScore *score);
|
||||||
|
gboolean clutter_score_is_playing (ClutterScore *score);
|
||||||
|
|
||||||
void
|
guint clutter_score_append (ClutterScore *score,
|
||||||
clutter_score_set_loop (ClutterScore *score,
|
ClutterTimeline *parent,
|
||||||
gboolean loop);
|
ClutterTimeline *timeline);
|
||||||
|
void clutter_score_remove (ClutterScore *score,
|
||||||
gboolean
|
guint id);
|
||||||
clutter_score_get_loop (ClutterScore *score);
|
void clutter_score_remove_all (ClutterScore *score);
|
||||||
|
ClutterTimeline *clutter_score_get_timeline (ClutterScore *score,
|
||||||
void
|
guint id);
|
||||||
clutter_score_rewind (ClutterScore *score);
|
GSList * clutter_score_list_timelines (ClutterScore *score);
|
||||||
|
|
||||||
gboolean
|
|
||||||
clutter_score_is_playing (ClutterScore *score);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_start (ClutterScore *score);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_stop (ClutterScore *score);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_pause (ClutterScore *score);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_append (ClutterScore *score,
|
|
||||||
ClutterTimeline *timeline_existing,
|
|
||||||
ClutterTimeline *timeline_new);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_add (ClutterScore *score,
|
|
||||||
ClutterTimeline *timeline);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_remove (ClutterScore *score,
|
|
||||||
ClutterTimeline *timeline_parent,
|
|
||||||
ClutterTimeline *timeline);
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_score_remove_all (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);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif /* __CLUTTER_SCORE_H__ */
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2007-12-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
* clutter.types:
|
||||||
|
* clutter-docs.sgml:
|
||||||
|
* clutter-sections.txt: Fix ClutterScore symbols.
|
||||||
|
|
||||||
2007-11-30 Emmanuele Bassi <ebassi@openedhand.com>
|
2007-11-30 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
* clutter-sections.txt: Update with the newly added API.
|
* clutter-sections.txt: Update with the newly added API.
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
<title>Base classes</title>
|
<title>Base classes</title>
|
||||||
|
|
||||||
<xi:include href="xml/clutter-timeline.xml"/>
|
<xi:include href="xml/clutter-timeline.xml"/>
|
||||||
|
<xi:include href="xml/clutter-score.xml"/>
|
||||||
<xi:include href="xml/clutter-alpha.xml"/>
|
<xi:include href="xml/clutter-alpha.xml"/>
|
||||||
<xi:include href="xml/clutter-behaviour.xml"/>
|
<xi:include href="xml/clutter-behaviour.xml"/>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@ -1212,12 +1212,15 @@ clutter_model_iter_get_type
|
|||||||
ClutterScore
|
ClutterScore
|
||||||
ClutterScoreClass
|
ClutterScoreClass
|
||||||
clutter_score_new
|
clutter_score_new
|
||||||
clutter_score_add
|
clutter_score_set_loop
|
||||||
|
clutter_score_get_loop
|
||||||
|
|
||||||
|
<SUBSECTION>
|
||||||
clutter_score_append
|
clutter_score_append
|
||||||
clutter_score_remove
|
clutter_score_remove
|
||||||
clutter_score_remove_all
|
clutter_score_remove_all
|
||||||
clutter_score_set_loop
|
clutter_score_get_timeline
|
||||||
clutter_score_get_loop
|
clutter_score_list_timelines
|
||||||
|
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
clutter_score_start
|
clutter_score_start
|
||||||
|
@ -24,3 +24,4 @@ clutter_script_get_type
|
|||||||
clutter_scriptable_get_type
|
clutter_scriptable_get_type
|
||||||
clutter_model_get_type
|
clutter_model_get_type
|
||||||
clutter_model_iter_get_type
|
clutter_model_iter_get_type
|
||||||
|
clutter_score_get_type
|
||||||
|
@ -2,6 +2,38 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
static gint level = 1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_timeline_started (ClutterScore *score,
|
||||||
|
ClutterTimeline *timeline)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
for (i = 0; i < level; i++)
|
||||||
|
g_print (" ");
|
||||||
|
|
||||||
|
g_print ("Started timeline: `%s'\n",
|
||||||
|
g_object_get_data (G_OBJECT (timeline), "timeline-name"));
|
||||||
|
|
||||||
|
level += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_timeline_completed (ClutterScore *score,
|
||||||
|
ClutterTimeline *timeline)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
level -= 1;
|
||||||
|
|
||||||
|
for (i = 0; i < level; i++)
|
||||||
|
g_print (" ");
|
||||||
|
|
||||||
|
g_print ("Completed timeline: `%s'\n",
|
||||||
|
g_object_get_data (G_OBJECT (timeline), "timeline-name"));
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -14,12 +46,38 @@ main (int argc, char **argv)
|
|||||||
clutter_init (&argc, &argv);
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
timeline_1 = clutter_timeline_new (10, 120);
|
timeline_1 = clutter_timeline_new (10, 120);
|
||||||
|
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_clone (timeline_1);
|
||||||
|
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_clone (timeline_1);
|
||||||
|
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_clone (timeline_1);
|
||||||
|
g_object_set_data_full (G_OBJECT (timeline_4),
|
||||||
|
"timeline-name", g_strdup ("Timeline 4"),
|
||||||
|
g_free);
|
||||||
|
|
||||||
|
|
||||||
score = clutter_score_new();
|
score = clutter_score_new();
|
||||||
clutter_score_add (score, timeline_1);
|
g_signal_connect (score, "timeline-started",
|
||||||
|
G_CALLBACK (on_timeline_started),
|
||||||
|
NULL);
|
||||||
|
g_signal_connect (score, "timeline-completed",
|
||||||
|
G_CALLBACK (on_timeline_completed),
|
||||||
|
NULL);
|
||||||
|
g_signal_connect (score, "completed",
|
||||||
|
G_CALLBACK (clutter_main_quit),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
clutter_score_append (score, NULL, timeline_1);
|
||||||
clutter_score_append (score, timeline_1, timeline_2);
|
clutter_score_append (score, timeline_1, timeline_2);
|
||||||
clutter_score_append (score, timeline_1, timeline_3);
|
clutter_score_append (score, timeline_1, timeline_3);
|
||||||
clutter_score_append (score, timeline_3, timeline_4);
|
clutter_score_append (score, timeline_3, timeline_4);
|
||||||
@ -32,6 +90,7 @@ main (int argc, char **argv)
|
|||||||
g_object_unref (timeline_1);
|
g_object_unref (timeline_1);
|
||||||
g_object_unref (timeline_2);
|
g_object_unref (timeline_2);
|
||||||
g_object_unref (timeline_3);
|
g_object_unref (timeline_3);
|
||||||
|
g_object_unref (timeline_4);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user