source: proiecte/PPPP/gdm/gui/simple-greeter/gdm-timer.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 9.7 KB
Line 
1/*
2 * Copyright (C) 2008 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Written by: Ray Strode <rstrode@redhat.com>
19 */
20
21#include "config.h"
22#include "gdm-timer.h"
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
29#include <dirent.h>
30#include <sys/stat.h>
31
32#include <glib.h>
33#include <glib/gi18n.h>
34#include <glib/gstdio.h>
35#include <gtk/gtk.h>
36
37#include "gdm-marshal.h"
38
39#define GDM_TIMER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_TIMER, GdmTimerPrivate))
40
41#ifndef GDM_TIMER_TICKS_PER_SECOND
42#define GDM_TIMER_TICKS_PER_SECOND 60
43#endif
44
45struct GdmTimerPrivate
46{
47        double start_time;
48        double duration;
49
50        guint  tick_timeout_id;
51
52        guint  is_started : 1;
53};
54
55enum {
56        PROP_0,
57        PROP_START_TIME,
58        PROP_DURATION,
59        PROP_IS_STARTED
60};
61
62enum {
63        TICK,
64        STOP,
65        NUMBER_OF_SIGNALS
66};
67
68static guint signals[NUMBER_OF_SIGNALS];
69
70static void  gdm_timer_class_init  (GdmTimerClass *klass);
71static void  gdm_timer_init        (GdmTimer      *timer);
72static void  gdm_timer_finalize    (GObject       *object);
73
74static void  gdm_timer_queue_next_tick (GdmTimer *timer,
75                                        double    when);
76
77G_DEFINE_TYPE (GdmTimer, gdm_timer, G_TYPE_OBJECT)
78
79static void
80gdm_timer_finalize (GObject *object)
81{
82        GdmTimer *timer;
83
84        timer = GDM_TIMER (object);
85
86        gdm_timer_stop (timer);
87
88        G_OBJECT_CLASS (gdm_timer_parent_class)->finalize (object);
89}
90
91static void
92gdm_timer_get_property (GObject        *object,
93                        guint           prop_id,
94                        GValue         *value,
95                        GParamSpec     *pspec)
96{
97        GdmTimer *timer;
98
99        timer = GDM_TIMER (object);
100
101        switch (prop_id) {
102        case PROP_START_TIME:
103                g_value_set_double (value, timer->priv->start_time);
104                break;
105        case PROP_DURATION:
106                g_value_set_double (value, timer->priv->duration);
107                break;
108        case PROP_IS_STARTED:
109                g_value_set_boolean (value, timer->priv->is_started);
110                break;
111        default:
112                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113                break;
114        }
115}
116
117static void
118gdm_timer_class_init (GdmTimerClass *klass)
119{
120        GObjectClass *object_class;
121
122        object_class = G_OBJECT_CLASS (klass);
123
124        object_class->finalize = gdm_timer_finalize;
125
126        object_class->get_property = gdm_timer_get_property;
127
128        signals[TICK] = g_signal_new ("tick",
129                                      G_TYPE_FROM_CLASS (object_class),
130                                      G_SIGNAL_RUN_LAST,
131                                      G_STRUCT_OFFSET (GdmTimerClass, tick),
132                                      NULL,
133                                      NULL,
134                                      gdm_marshal_VOID__DOUBLE,
135                                      G_TYPE_NONE,
136                                      1, G_TYPE_DOUBLE);
137        signals[STOP] = g_signal_new ("stop",
138                                      G_TYPE_FROM_CLASS (object_class),
139                                      G_SIGNAL_RUN_LAST,
140                                      G_STRUCT_OFFSET (GdmTimerClass, stop),
141                                      NULL,
142                                      NULL,
143                                      g_cclosure_marshal_VOID__VOID,
144                                      G_TYPE_NONE, 0);
145
146        g_object_class_install_property (object_class,
147                                         PROP_DURATION,
148                                         g_param_spec_double ("duration",
149                                                              _("Duration"),
150                                                              _("Number of seconds until timer stops"),
151                                                              0.0, G_MAXDOUBLE, 0.0,
152                                                              G_PARAM_READABLE));
153
154        g_object_class_install_property (object_class,
155                                         PROP_START_TIME,
156                                         g_param_spec_double ("start-time",
157                                                              _("Start time"),
158                                                              _("Time the timer was started"),
159                                                              0.0, G_MAXDOUBLE, 0.0,
160                                                              G_PARAM_READABLE));
161
162        g_object_class_install_property (object_class,
163                                         PROP_IS_STARTED,
164                                         g_param_spec_boolean ("is-started",
165                                                               _("Is it Running?"),
166                                                               _("Whether or not the timer "
167                                                                 "is currently ticking"),
168                                                               FALSE, G_PARAM_READABLE));
169
170
171
172        g_type_class_add_private (klass, sizeof (GdmTimerPrivate));
173}
174
175static void
176gdm_timer_init (GdmTimer *timer)
177{
178        timer->priv = GDM_TIMER_GET_PRIVATE (timer);
179}
180
181GdmTimer *
182gdm_timer_new (void)
183{
184        GObject *object;
185
186        object = g_object_new (GDM_TYPE_TIMER, NULL);
187
188        return GDM_TIMER (object);
189}
190
191static double
192get_current_time (void)
193{
194  const double microseconds_per_second = 1000000.0;
195  double       timestamp;
196  GTimeVal     now;
197
198  g_get_current_time (&now);
199
200  timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) /
201               microseconds_per_second;
202
203  return timestamp;
204}
205
206static double
207do_tick (GdmTimer *timer,
208         double    progress,
209         double    current_time)
210{
211        static const double frequency = 1.0 / GDM_TIMER_TICKS_PER_SECOND;
212        double next_tick;
213        double time_before_tick;
214        double tick_duration;
215
216        time_before_tick = current_time;
217        g_signal_emit (G_OBJECT (timer), signals[TICK], 0, progress);
218
219        current_time = get_current_time ();
220        tick_duration = current_time - time_before_tick;
221
222        next_tick = MAX (frequency - tick_duration, 0.0);
223
224        return next_tick;
225}
226
227static gboolean
228on_tick_timeout (GdmTimer *timer)
229{
230        double progress;
231        double current_time;
232        double elapsed_time;
233        double next_tick;
234
235        current_time = get_current_time ();
236        elapsed_time = current_time - timer->priv->start_time;
237        progress = elapsed_time / timer->priv->duration;
238
239        timer->priv->tick_timeout_id = 0;
240
241        g_object_ref (timer);
242        if (progress > 0.999) {
243                do_tick (timer, 1.0, current_time);
244                if (timer->priv->is_started) {
245                        gdm_timer_stop (timer);
246                }
247        } else {
248                next_tick = do_tick (timer, progress, current_time);
249                if (timer->priv->is_started) {
250                        gdm_timer_queue_next_tick (timer, next_tick);
251                }
252        }
253        g_object_unref (timer);
254
255        return FALSE;
256}
257
258static void
259gdm_timer_queue_next_tick (GdmTimer *timer,
260                           double    when)
261{
262        if (timer->priv->tick_timeout_id != 0) {
263                return;
264        }
265
266        if (!timer->priv->is_started) {
267                return;
268        }
269
270        timer->priv->tick_timeout_id = g_timeout_add ((guint) (when * 1000),
271                                                      (GSourceFunc) on_tick_timeout,
272                                                      timer);
273}
274
275static void
276gdm_timer_set_is_started (GdmTimer *timer,
277                          gboolean  is_started)
278{
279        timer->priv->is_started = is_started;
280        g_object_notify (G_OBJECT (timer), "is-started");
281}
282
283void
284gdm_timer_start (GdmTimer *timer,
285                 double    number_of_seconds)
286{
287        double next_tick;
288
289        g_return_if_fail (GDM_IS_TIMER (timer));
290        g_return_if_fail (number_of_seconds > G_MINDOUBLE);
291        g_return_if_fail (!timer->priv->is_started);
292
293        timer->priv->start_time = get_current_time ();
294        timer->priv->duration = number_of_seconds;
295
296        g_assert (timer->priv->tick_timeout_id == 0);
297        gdm_timer_set_is_started (timer, TRUE);
298
299        g_object_ref (timer);
300        next_tick = do_tick (timer, 0.0, timer->priv->start_time);
301        gdm_timer_queue_next_tick (timer, next_tick);
302        g_object_unref (timer);
303}
304
305void
306gdm_timer_stop (GdmTimer *timer)
307{
308        g_return_if_fail (GDM_IS_TIMER (timer));
309
310        if (!timer->priv->is_started) {
311                return;
312        }
313
314        if (timer->priv->tick_timeout_id != 0) {
315                g_source_remove (timer->priv->tick_timeout_id);
316                timer->priv->tick_timeout_id = 0;
317        }
318
319        gdm_timer_set_is_started (timer, FALSE);
320        g_signal_emit (G_OBJECT (timer), signals[STOP], 0);
321}
322
323gboolean
324gdm_timer_is_started (GdmTimer *timer)
325{
326        g_return_val_if_fail (GDM_IS_TIMER (timer), FALSE);
327
328        return timer->priv->is_started;
329}
Note: See TracBrowser for help on using the repository browser.