Header cleanup: try to include as little as possible; this will probably speed up...
[platform/upstream/gstreamer.git] / gst / gstclock.c
1 /* Gnome-Streamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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 GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <sys/time.h>
21 //#define DEBUG_ENABLED
22 #include "gstclock.h"
23 #include "gstdebug.h"
24 #include "gstsink.h"
25
26 static GstClock *the_system_clock = NULL;
27
28 /**
29  * gst_clock_new:
30  * @name: the name of the new clock
31  *
32  * create a new clock element
33  *
34  * Returns: the new clock element
35  */
36 GstClock*
37 gst_clock_new (gchar *name) 
38 {
39   GstClock *clock = (GstClock *) g_malloc(sizeof(GstClock));
40   
41   clock->name = g_strdup (name);
42   clock->sinkobjects = NULL;
43   clock->sinkmutex = g_mutex_new ();
44   clock->lock = g_mutex_new ();
45   g_mutex_lock (clock->sinkmutex);
46   
47   clock->num = 0;
48   clock->num_locked = 0;
49   clock->locking = FALSE;
50   
51   return clock;
52 }
53
54 GstClock*
55 gst_clock_get_system(void) 
56 {
57   if (the_system_clock == NULL) {
58     the_system_clock = gst_clock_new ("system_clock");
59     gst_clock_reset (the_system_clock);
60   }
61   return the_system_clock;
62 }
63
64 void 
65 gst_clock_register (GstClock *clock, GstObject *obj) 
66 {
67   if (GST_IS_SINK (obj)) {
68     DEBUG("gst_clock: setting registered sink object 0x%p\n", obj);
69     clock->sinkobjects = g_list_append (clock->sinkobjects, obj);
70     clock->num++;
71   }
72 }
73
74 void 
75 gst_clock_set (GstClock *clock, GstClockTime time) 
76 {
77   struct timeval tfnow;
78   GstClockTime now;
79
80   gettimeofday (&tfnow, (struct timezone *)NULL);
81   now = tfnow.tv_sec*1000000LL+tfnow.tv_usec;
82   g_mutex_lock (clock->lock);
83   clock->start_time = now - time;
84   g_mutex_unlock (clock->lock);
85   DEBUG("gst_clock: setting clock to %llu %llu %llu\n", time, now, clock->start_time);
86 }
87
88 GstClockTimeDiff 
89 gst_clock_current_diff (GstClock *clock, GstClockTime time)
90 {
91   struct timeval tfnow;
92   GstClockTime now;
93
94   gettimeofday (&tfnow, (struct timezone *)NULL);
95   g_mutex_lock (clock->lock);
96   now = ((guint64)tfnow.tv_sec*1000000LL+tfnow.tv_usec) - (guint64)clock->start_time; 
97   g_mutex_unlock (clock->lock);
98
99   return GST_CLOCK_DIFF (time, now);
100 }
101
102 void 
103 gst_clock_reset (GstClock *clock) 
104 {
105   struct timeval tfnow;
106
107   gettimeofday (&tfnow, (struct timezone *)NULL);
108   g_mutex_lock (clock->lock);
109   clock->start_time = ((guint64)tfnow.tv_sec)*1000000LL+tfnow.tv_usec;
110   clock->current_time = clock->start_time;
111   clock->adjust = 0LL;
112   DEBUG("gst_clock: setting start clock %llu\n", clock->start_time);
113   g_mutex_unlock (clock->lock);
114 }
115
116 void 
117 gst_clock_wait (GstClock *clock, GstClockTime time, GstObject *obj) 
118 {
119   struct timeval tfnow;
120   GstClockTime now;
121   GstClockTimeDiff diff;
122
123
124   gettimeofday (&tfnow, (struct timezone *)NULL);
125   g_mutex_lock (clock->lock);
126   now = tfnow.tv_sec*1000000LL+tfnow.tv_usec - clock->start_time;
127
128   diff = GST_CLOCK_DIFF (time, now);
129   // if we are not behind wait a bit
130   DEBUG("gst_clock: %s waiting for time %08llu %08llu %08lld\n", gst_element_get_name(GST_ELEMENT(obj)), time, now, diff);
131    
132   g_mutex_unlock (clock->lock);
133   if (diff > 10000 ) {
134     tfnow.tv_usec = (diff % 1000000);
135     tfnow.tv_sec = diff / 1000000;
136     // FIXME, this piece of code does not work with egcs optimisations on, had to use the following line
137     if (!tfnow.tv_sec) {
138       select(0, NULL, NULL, NULL, &tfnow);
139     }
140     else DEBUG("gst_clock: %s waiting %u %llu %llu %llu seconds\n", gst_element_get_name(GST_ELEMENT(obj)), 
141                     (int)tfnow.tv_sec, now, diff, time);
142   }
143   DEBUG("gst_clock: %s waiting for time %08llu %08llu %08lld done \n", gst_element_get_name(GST_ELEMENT(obj)), time, now, diff);
144 }