fix doc build fix autogen
[platform/upstream/gstreamer.git] / gst / gstsystemclock.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wim.taymans@chello.be>
4  *
5  * gstsystemclock.c: Default clock, uses the system clock
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <sys/time.h>
24
25 #include "gst_private.h"
26 #include "gstinfo.h"
27
28 #include "gstsystemclock.h"
29
30 static GstClock *_the_system_clock = NULL;
31
32 static void                     gst_system_clock_class_init     (GstSystemClockClass *klass);
33 static void                     gst_system_clock_init           (GstSystemClock *clock);
34 static void                     gst_system_clock_dispose        (GObject *object);
35
36 static GstClockTime             gst_system_clock_get_internal_time      (GstClock *clock);
37 static guint64                  gst_system_clock_get_resolution (GstClock *clock);
38 static GstClockEntryStatus      gst_system_clock_wait           (GstClock *clock, GstClockEntry *entry);
39 static void                     gst_system_clock_unlock         (GstClock *clock, GstClockEntry *entry);
40
41 static GStaticMutex _gst_sysclock_mutex = G_STATIC_MUTEX_INIT;
42
43 static GstClockClass *parent_class = NULL;
44 /* static guint gst_system_clock_signals[LAST_SIGNAL] = { 0 }; */
45
46 GType
47 gst_system_clock_get_type (void)
48 {
49   static GType clock_type = 0;
50
51   if (!clock_type) {
52     static const GTypeInfo clock_info = {
53       sizeof (GstSystemClockClass),
54       NULL,
55       NULL,
56       (GClassInitFunc) gst_system_clock_class_init,
57       NULL,
58       NULL,
59       sizeof (GstSystemClock),
60       4,
61       (GInstanceInitFunc) gst_system_clock_init,
62       NULL
63     };
64     clock_type = g_type_register_static (GST_TYPE_CLOCK, "GstSystemClock", 
65                                          &clock_info, 0);
66   }
67   return clock_type;
68 }
69
70 static void
71 gst_system_clock_class_init (GstSystemClockClass *klass)
72 {
73   GObjectClass *gobject_class;
74   GstObjectClass *gstobject_class;
75   GstClockClass *gstclock_class;
76
77   gobject_class = (GObjectClass*) klass;
78   gstobject_class = (GstObjectClass*) klass;
79   gstclock_class = (GstClockClass*) klass;
80
81   parent_class = g_type_class_ref (GST_TYPE_CLOCK);
82
83   gobject_class->dispose                = gst_system_clock_dispose;
84
85   gstclock_class->get_internal_time     = gst_system_clock_get_internal_time;
86   gstclock_class->get_resolution        = gst_system_clock_get_resolution;
87   gstclock_class->wait                  = gst_system_clock_wait;
88   gstclock_class->unlock                = gst_system_clock_unlock;
89 }
90
91 static void
92 gst_system_clock_init (GstSystemClock *clock)
93 {
94   clock->mutex = g_mutex_new();
95   clock->cond = g_cond_new ();
96 }
97
98 static void
99 gst_system_clock_dispose (GObject *object)
100 {
101   GstClock *clock = (GstClock *) object;
102   GstSystemClock *sysclock = (GstSystemClock *) object;
103
104   /* there are subclasses of GstSystemClock running around... */
105   if (_the_system_clock == clock) {
106     g_warning ("disposing systemclock!");
107
108     /* no parent dispose here, this is bad enough already */
109   } else {
110     G_OBJECT_CLASS (parent_class)->dispose (object);
111
112     /* FIXME: Notifying before freeing? */
113     g_cond_free (sysclock->cond);
114     g_mutex_free (sysclock->mutex);
115   }
116 }
117
118 /**
119  * gst_system_clock_obtain 
120  *
121  * Get a handle to the default system clock.
122  *
123  * Returns: the default clock.
124  */
125 GstClock*
126 gst_system_clock_obtain (void)
127 {
128   GstClock *clock = _the_system_clock;
129
130   if (clock == NULL) {
131     g_static_mutex_lock (&_gst_sysclock_mutex);
132     if (_the_system_clock != NULL) {
133       clock = _the_system_clock;
134       g_static_mutex_unlock (&_gst_sysclock_mutex);
135       goto have_clock;
136     }
137       
138     clock = GST_CLOCK (g_object_new (GST_TYPE_SYSTEM_CLOCK, NULL));
139     
140     gst_object_set_name (GST_OBJECT (clock), "GstSystemClock");
141
142     gst_object_ref (GST_OBJECT (clock));
143     gst_object_sink (GST_OBJECT (clock));
144
145     _the_system_clock = clock;
146     g_static_mutex_unlock (&_gst_sysclock_mutex);
147   }
148
149 have_clock:
150   gst_object_ref (GST_OBJECT (clock));
151   return clock;
152 }
153
154 static GstClockTime
155 gst_system_clock_get_internal_time (GstClock *clock)
156 {
157   GTimeVal timeval;
158
159   g_get_current_time (&timeval);
160   
161   return GST_TIMEVAL_TO_TIME (timeval);
162 }
163
164 static guint64
165 gst_system_clock_get_resolution (GstClock *clock)
166 {
167   return 1 * GST_USECOND;
168 }
169
170 static GstClockEntryStatus
171 gst_system_clock_wait (GstClock *clock, GstClockEntry *entry)
172 {
173   GstClockEntryStatus res;
174   GstClockTime current, target;
175   gint64 diff;
176   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
177
178   current = gst_clock_get_time (clock);
179   diff = GST_CLOCK_ENTRY_TIME (entry) - current;
180
181   if (diff + clock->max_diff < 0) {
182     GST_WARNING_OBJECT (clock, "clock is way behind: %" G_GINT64_FORMAT
183         "s (max allowed is %" G_GINT64_FORMAT "s", -diff, clock->max_diff);
184     return GST_CLOCK_ENTRY_EARLY;
185   }
186   
187   target = gst_system_clock_get_internal_time (clock) + diff;
188
189   GST_CAT_DEBUG (GST_CAT_CLOCK, "real_target %" G_GUINT64_FORMAT
190                             " target %" G_GUINT64_FORMAT
191                             " now %" G_GUINT64_FORMAT,
192                             target, GST_CLOCK_ENTRY_TIME (entry), current);
193
194   if (((gint64)target) > 0) {
195     GTimeVal tv;
196
197     GST_TIME_TO_TIMEVAL (target, tv);
198     g_mutex_lock (sysclock->mutex);
199     g_cond_timed_wait (sysclock->cond, sysclock->mutex, &tv);
200     g_mutex_unlock (sysclock->mutex);
201     res = entry->status;
202   }
203   else {
204     res = GST_CLOCK_ENTRY_EARLY;
205   }
206   return res;
207 }
208
209 static void
210 gst_system_clock_unlock (GstClock *clock, GstClockEntry *entry)
211 {
212   GstSystemClock *sysclock = GST_SYSTEM_CLOCK (clock);
213
214   g_mutex_lock (sysclock->mutex);
215   g_cond_broadcast (sysclock->cond);
216   g_mutex_unlock (sysclock->mutex);
217 }