2 * this file is part of evince, a gnome document viewer
4 * Copyright (C) 2007 Carlos Garnacho <carlos@imendio.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
25 #include "ev-timeline.h"
27 #define EV_TIMELINE_GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EV_TYPE_TIMELINE, EvTimelinePriv))
28 #define MSECS_PER_SEC 1000
29 #define FRAME_INTERVAL(nframes) (MSECS_PER_SEC / nframes)
30 #define DEFAULT_FPS 30
32 typedef struct EvTimelinePriv EvTimelinePriv;
34 struct EvTimelinePriv {
59 static guint signals [LAST_SIGNAL] = { 0, };
62 G_DEFINE_TYPE (EvTimeline, ev_timeline, G_TYPE_OBJECT)
66 ev_timeline_init (EvTimeline *timeline)
70 priv = EV_TIMELINE_GET_PRIV (timeline);
72 priv->fps = DEFAULT_FPS;
77 ev_timeline_set_property (GObject *object,
84 timeline = EV_TIMELINE (object);
88 ev_timeline_set_fps (timeline, g_value_get_uint (value));
91 ev_timeline_set_duration (timeline, g_value_get_uint (value));
94 ev_timeline_set_loop (timeline, g_value_get_boolean (value));
97 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
102 ev_timeline_get_property (GObject *object,
107 EvTimeline *timeline;
108 EvTimelinePriv *priv;
110 timeline = EV_TIMELINE (object);
111 priv = EV_TIMELINE_GET_PRIV (timeline);
115 g_value_set_uint (value, priv->fps);
118 g_value_set_uint (value, priv->duration);
121 g_value_set_boolean (value, priv->loop);
124 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129 ev_timeline_finalize (GObject *object)
131 EvTimelinePriv *priv;
133 priv = EV_TIMELINE_GET_PRIV (object);
135 if (priv->source_id) {
136 g_source_remove (priv->source_id);
141 g_timer_destroy (priv->timer);
143 G_OBJECT_CLASS (ev_timeline_parent_class)->finalize (object);
147 ev_timeline_run_frame (EvTimeline *timeline)
149 EvTimelinePriv *priv;
153 GDK_THREADS_ENTER ();
155 priv = EV_TIMELINE_GET_PRIV (timeline);
157 elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000);
158 progress = (gdouble) elapsed_time / priv->duration;
159 progress = CLAMP (progress, 0., 1.);
161 g_signal_emit (timeline, signals [FRAME], 0, progress);
163 if (progress >= 1.0) {
165 if (priv->source_id) {
166 g_source_remove (priv->source_id);
170 g_signal_emit (timeline, signals [FINISHED], 0);
173 ev_timeline_rewind (timeline);
177 GDK_THREADS_LEAVE ();
183 ev_timeline_real_start (EvTimeline *timeline)
185 EvTimelinePriv *priv;
187 priv = EV_TIMELINE_GET_PRIV (timeline);
189 if (!priv->source_id) {
191 g_timer_continue (priv->timer);
193 priv->timer = g_timer_new ();
196 g_assert (priv->fps > 0);
198 g_signal_emit (timeline, signals [STARTED], 0);
200 priv->source_id = g_timeout_add (FRAME_INTERVAL (priv->fps),
201 (GSourceFunc) ev_timeline_run_frame,
207 ev_timeline_class_init (EvTimelineClass *class)
209 GObjectClass *object_class = G_OBJECT_CLASS (class);
211 object_class->set_property = ev_timeline_set_property;
212 object_class->get_property = ev_timeline_get_property;
213 object_class->finalize = ev_timeline_finalize;
215 class->start = ev_timeline_real_start;
217 g_object_class_install_property (object_class,
219 g_param_spec_uint ("fps",
221 "Frames per second for the timeline",
226 g_object_class_install_property (object_class,
228 g_param_spec_uint ("duration",
229 "Animation Duration",
230 "Animation Duration",
235 g_object_class_install_property (object_class,
237 g_param_spec_boolean ("loop",
239 "Whether the timeline loops or not",
243 g_signal_new ("started",
244 G_TYPE_FROM_CLASS (object_class),
246 G_STRUCT_OFFSET (EvTimelineClass, started),
248 g_cclosure_marshal_VOID__VOID,
252 g_signal_new ("paused",
253 G_TYPE_FROM_CLASS (object_class),
255 G_STRUCT_OFFSET (EvTimelineClass, paused),
257 g_cclosure_marshal_VOID__VOID,
261 g_signal_new ("finished",
262 G_TYPE_FROM_CLASS (object_class),
264 G_STRUCT_OFFSET (EvTimelineClass, finished),
266 g_cclosure_marshal_VOID__VOID,
270 g_signal_new ("frame",
271 G_TYPE_FROM_CLASS (object_class),
273 G_STRUCT_OFFSET (EvTimelineClass, frame),
275 g_cclosure_marshal_VOID__DOUBLE,
279 g_type_class_add_private (class, sizeof (EvTimelinePriv));
283 ev_timeline_new (guint duration)
285 return g_object_new (EV_TYPE_TIMELINE,
286 "duration", duration,
291 ev_timeline_start (EvTimeline *timeline)
293 g_return_if_fail (EV_IS_TIMELINE (timeline));
295 EV_TIMELINE_GET_CLASS (timeline)->start (timeline);
299 ev_timeline_pause (EvTimeline *timeline)
301 EvTimelinePriv *priv;
303 g_return_if_fail (EV_IS_TIMELINE (timeline));
305 priv = EV_TIMELINE_GET_PRIV (timeline);
307 if (priv->source_id) {
308 g_source_remove (priv->source_id);
310 g_timer_stop (priv->timer);
311 g_signal_emit (timeline, signals [PAUSED], 0);
316 ev_timeline_rewind (EvTimeline *timeline)
318 EvTimelinePriv *priv;
320 g_return_if_fail (EV_IS_TIMELINE (timeline));
322 priv = EV_TIMELINE_GET_PRIV (timeline);
324 /* destroy and re-create timer if neccesary */
326 g_timer_destroy (priv->timer);
328 if (ev_timeline_is_running (timeline))
329 priv->timer = g_timer_new ();
336 ev_timeline_is_running (EvTimeline *timeline)
338 EvTimelinePriv *priv;
340 g_return_val_if_fail (EV_IS_TIMELINE (timeline), FALSE);
342 priv = EV_TIMELINE_GET_PRIV (timeline);
344 return (priv->source_id != 0);
348 ev_timeline_get_fps (EvTimeline *timeline)
350 EvTimelinePriv *priv;
352 g_return_val_if_fail (EV_IS_TIMELINE (timeline), 1);
354 priv = EV_TIMELINE_GET_PRIV (timeline);
359 ev_timeline_set_fps (EvTimeline *timeline,
362 EvTimelinePriv *priv;
364 g_return_if_fail (EV_IS_TIMELINE (timeline));
366 priv = EV_TIMELINE_GET_PRIV (timeline);
370 if (ev_timeline_is_running (timeline)) {
371 g_source_remove (priv->source_id);
372 priv->source_id = g_timeout_add (FRAME_INTERVAL (priv->fps),
373 (GSourceFunc) ev_timeline_run_frame,
377 g_object_notify (G_OBJECT (timeline), "fps");
381 ev_timeline_get_loop (EvTimeline *timeline)
383 EvTimelinePriv *priv;
385 g_return_val_if_fail (EV_IS_TIMELINE (timeline), FALSE);
387 priv = EV_TIMELINE_GET_PRIV (timeline);
392 ev_timeline_set_loop (EvTimeline *timeline,
395 EvTimelinePriv *priv;
397 g_return_if_fail (EV_IS_TIMELINE (timeline));
399 priv = EV_TIMELINE_GET_PRIV (timeline);
402 g_object_notify (G_OBJECT (timeline), "loop");
406 ev_timeline_set_duration (EvTimeline *timeline,
409 EvTimelinePriv *priv;
411 g_return_if_fail (EV_IS_TIMELINE (timeline));
413 priv = EV_TIMELINE_GET_PRIV (timeline);
415 priv->duration = duration;
417 g_object_notify (G_OBJECT (timeline), "duration");
421 ev_timeline_get_duration (EvTimeline *timeline)
423 EvTimelinePriv *priv;
425 g_return_val_if_fail (EV_IS_TIMELINE (timeline), 0);
427 priv = EV_TIMELINE_GET_PRIV (timeline);
429 return priv->duration;
433 ev_timeline_get_progress (EvTimeline *timeline)
435 EvTimelinePriv *priv;
439 g_return_val_if_fail (EV_IS_TIMELINE (timeline), 0.0);
441 priv = EV_TIMELINE_GET_PRIV (timeline);
446 elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000);
447 progress = (gdouble) elapsed_time / priv->duration;
449 return CLAMP (progress, 0., 1.);