Various fixes to ClutterTimeline
Emit the ClutterTimeline::new-frame signal only if we arrive there with an active timeout source. Also, make sure to take a reference on the timeout when emitting signals. If the timeline is advancing of zero frames, bump it up to one frame. (bug 471, Rob Bradford) If the user called clutter_timeline_pause() while in the ::new-frame handler the timeout is removed and the timeline is reset, while the correct behaviour should be to simply return. (#371, Johan Bilien) If we skipped the last frames and we ended up over the frame number, emit the ::new-frame signal with the last frame before emitting the ::completed signal. Remove the call to clutter_timeline_stop() when reaching the end of the timeline: it was used just to remove the timeout source and it emitted the ::paused signal, which doesn't make any sense. Also rewind the timeline after emitting the ::completed signal, so that calling get_current_frame() in the ::completed signal handlers still work.
This commit is contained in:
parent
c8a0faab73
commit
92910e3e2f
@ -399,26 +399,44 @@ timeline_timeout_func (gpointer data)
|
|||||||
GTimeVal timeval;
|
GTimeVal timeval;
|
||||||
gint n_frames;
|
gint n_frames;
|
||||||
gulong msecs;
|
gulong msecs;
|
||||||
|
gboolean retval = TRUE;
|
||||||
|
|
||||||
priv = timeline->priv;
|
priv = timeline->priv;
|
||||||
|
|
||||||
CLUTTER_TIMESTAMP (SCHEDULER, "Timeline:%p activated\n", timeline);
|
if (!timeline)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (SCHEDULER,
|
||||||
|
"The timeline [%p] has been disposed",
|
||||||
|
timeline);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->timeout_id)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (SCHEDULER,
|
||||||
|
"The timeline [%p] has been removed",
|
||||||
|
timeline);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_ref (timeline);
|
||||||
|
|
||||||
/* Figure out potential frame skips */
|
/* Figure out potential frame skips */
|
||||||
g_get_current_time (&timeval);
|
g_get_current_time (&timeval);
|
||||||
|
|
||||||
/* Fire off signal */
|
CLUTTER_TIMESTAMP (SCHEDULER, "Timeline [%p] activated (cur: %d)\n",
|
||||||
g_signal_emit (timeline, timeline_signals[NEW_FRAME],
|
timeline,
|
||||||
0, priv->current_frame_num);
|
priv->current_frame_num);
|
||||||
|
|
||||||
/* Signal frees timeline ? */
|
/* Fire off signal */
|
||||||
if (timeline == NULL)
|
g_signal_emit (timeline, timeline_signals[NEW_FRAME], 0,
|
||||||
return FALSE;
|
priv->current_frame_num);
|
||||||
|
|
||||||
/* Signal removes source ? */
|
/* Signal removes source ? */
|
||||||
if (!priv->timeout_id)
|
if (!priv->timeout_id)
|
||||||
{
|
{
|
||||||
clutter_timeline_stop (timeline);
|
g_object_unref (timeline);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,15 +447,17 @@ timeline_timeout_func (gpointer data)
|
|||||||
*/
|
*/
|
||||||
msecs = ((timeval.tv_sec - priv->start_frame_secs) * 1000)
|
msecs = ((timeval.tv_sec - priv->start_frame_secs) * 1000)
|
||||||
+ (timeval.tv_usec / 1000);
|
+ (timeval.tv_usec / 1000);
|
||||||
n_frames = (msecs - priv->last_frame_msecs ) / (1000 / priv->fps);
|
n_frames = (msecs - priv->last_frame_msecs)
|
||||||
if (n_frames < 0)
|
/ (1000 / priv->fps);
|
||||||
n_frames = 1;
|
|
||||||
|
|
||||||
if (n_frames > 1)
|
if (n_frames <= 0)
|
||||||
|
n_frames = 1;
|
||||||
|
else if (n_frames > 1)
|
||||||
{
|
{
|
||||||
CLUTTER_TIMESTAMP (SCHEDULER,
|
CLUTTER_TIMESTAMP (SCHEDULER,
|
||||||
"Timeline %p, skipping %i frames\n",
|
"Timeline [%p], skipping %d frames\n",
|
||||||
timeline, n_frames);
|
timeline,
|
||||||
|
n_frames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -457,28 +477,54 @@ timeline_timeout_func (gpointer data)
|
|||||||
/* Handle loop or stop */
|
/* Handle loop or stop */
|
||||||
if (priv->current_frame_num > priv->n_frames)
|
if (priv->current_frame_num > priv->n_frames)
|
||||||
{
|
{
|
||||||
|
guint frame_diff;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (SCHEDULER,
|
||||||
|
"Timeline [%p] completed (cur: %d, tot: %d, drop: %d)",
|
||||||
|
timeline,
|
||||||
|
priv->current_frame_num,
|
||||||
|
priv->n_frames,
|
||||||
|
n_frames - 1);
|
||||||
|
|
||||||
|
frame_diff = priv->current_frame_num - priv->n_frames;
|
||||||
priv->current_frame_num = priv->n_frames;
|
priv->current_frame_num = priv->n_frames;
|
||||||
|
|
||||||
if (n_frames > 1)
|
/* if we skipped some frame to get here let's see whether we still need
|
||||||
|
* to emit the last new-frame signal with the last frame
|
||||||
|
*/
|
||||||
|
if (frame_diff)
|
||||||
{
|
{
|
||||||
g_signal_emit (timeline, timeline_signals[NEW_FRAME],
|
g_signal_emit (timeline, timeline_signals[NEW_FRAME], 0,
|
||||||
0, priv->current_frame_num);
|
priv->current_frame_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->loop)
|
if (priv->loop)
|
||||||
{
|
{
|
||||||
clutter_timeline_rewind (timeline);
|
|
||||||
g_signal_emit (timeline, timeline_signals[COMPLETED], 0);
|
g_signal_emit (timeline, timeline_signals[COMPLETED], 0);
|
||||||
|
clutter_timeline_rewind (timeline);
|
||||||
|
|
||||||
|
retval = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_timeline_stop (timeline);
|
if (priv->timeout_id)
|
||||||
|
{
|
||||||
|
timeout_remove (priv->timeout_id);
|
||||||
|
priv->timeout_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->last_frame_msecs = 0;
|
||||||
|
|
||||||
g_signal_emit (timeline, timeline_signals[COMPLETED], 0);
|
g_signal_emit (timeline, timeline_signals[COMPLETED], 0);
|
||||||
return FALSE;
|
clutter_timeline_rewind (timeline);
|
||||||
|
|
||||||
|
retval = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
g_object_unref (timeline);
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -559,7 +605,6 @@ clutter_timeline_pause (ClutterTimeline *timeline)
|
|||||||
priv->timeout_id = 0;
|
priv->timeout_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->timeout_id = 0;
|
|
||||||
priv->last_frame_msecs = 0;
|
priv->last_frame_msecs = 0;
|
||||||
|
|
||||||
g_signal_emit (timeline, timeline_signals[PAUSED], 0);
|
g_signal_emit (timeline, timeline_signals[PAUSED], 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user