Makefile.am fixes
[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
24 static GstClock *the_system_clock = NULL;
25 static int num;
26
27 /**
28  * gst_clock_new:
29  * @name: the name of the new clock
30  *
31  * create a new clock element
32  *
33  * Returns: the new clock element
34  */
35 GstClock *gst_clock_new(gchar *name) {
36   GstClock *clock = (GstClock *) g_malloc(sizeof(GstClock));
37   clock->name = g_strdup(name);
38   clock->sinkobjects = NULL;
39   clock->sinkmutex = g_mutex_new();
40   clock->lock = g_mutex_new();
41   g_mutex_lock(clock->sinkmutex);
42   num =0;
43   clock->locking = TRUE;
44   return clock;
45 }
46
47 GstClock *gst_clock_get_system() {
48   if (the_system_clock == NULL) {
49     the_system_clock = gst_clock_new("system_clock");
50     gst_clock_reset(the_system_clock);
51   }
52   return the_system_clock;
53 }
54
55 void gst_clock_register(GstClock *clock, GstObject *obj) {
56   if (GST_IS_SINK(obj)) {
57     DEBUG("gst_clock: registered sink object 0x%p\n", obj);
58     clock->sinkobjects = g_list_append(clock->sinkobjects, obj);
59     num++;
60   }
61 }
62
63 void gst_clock_set(GstClock *clock, GstClockTime time) {
64   struct timeval tfnow;
65   GstClockTime target, now;
66
67   g_mutex_lock(clock->lock);
68   gettimeofday(&tfnow, (struct timezone *)NULL);
69   now = tfnow.tv_sec*1000000+tfnow.tv_usec;
70   clock->adjust = now - (clock->start_time + time);
71   clock->current_time = (clock->start_time + time);
72   //DEBUG("gst_clock: setting clock to %llu %llu %lld\n", (guint64)clock->start_time+time, (guint64)now, (gint64)clock->adjust);
73   g_mutex_unlock(clock->lock);
74 }
75
76 void gst_clock_reset(GstClock *clock) {
77   struct timeval tfnow;
78
79   gettimeofday(&tfnow, (struct timezone *)NULL);
80   clock->start_time = tfnow.tv_sec*1000000+tfnow.tv_usec;
81   clock->current_time = clock->start_time;
82   clock->adjust = 0LL;
83   DEBUG("gst_clock: setting start clock %llu\n", clock->start_time);
84 }
85
86 void gst_clock_wait(GstClock *clock, GstClockTime time, GstObject *obj) {
87   struct timeval tfnow;
88   GstClockTime target, now;
89   GstClockTimeDiff diff;
90   GList *elements;
91
92   g_mutex_lock(clock->lock);
93   elements = clock->sinkobjects;
94   while (elements && clock->locking) {
95     if (elements->data == obj) {
96       DEBUG("gst_clock: registered sink object 0x%p\n", obj);
97       num--;
98       if (num) {
99         DEBUG("gst_clock: 0x%p locked\n", obj);
100         g_mutex_unlock(clock->lock);
101         g_mutex_lock(clock->sinkmutex);
102         g_mutex_lock(clock->lock);
103         clock->locking = FALSE;
104       }
105       else {
106         gst_clock_reset(clock);
107         DEBUG("gst_clock: unlock all %p\n", obj);
108         g_mutex_unlock(clock->sinkmutex);
109         clock->locking = FALSE;
110       }
111       break;
112     }
113     elements = g_list_next(elements);
114   }
115
116   target = clock->start_time + time;
117   gettimeofday(&tfnow, (struct timezone *)NULL);
118   now = tfnow.tv_sec*1000000+tfnow.tv_usec + clock->adjust;
119   //now = clock->current_time + clock->adjust;
120
121   //DEBUG("gst_clock: 0x%p waiting for time %llu %llu\n", obj, time, target);
122
123   diff = GST_CLOCK_DIFF(target, now);
124   // if we are not behind wait a bit
125    
126   if (diff > 1000 ) {
127     tfnow.tv_usec = diff % 1000000;
128     tfnow.tv_sec = diff / 1000000;
129     // FIXME, this piece of code does not work with egcs optimisations on, had to use the following line
130     if (tfnow.tv_sec) fprintf(stderr, "gst_clock: waiting %u %llu %llu %llu seconds\n", (int)tfnow.tv_sec, now, diff, target);
131     g_mutex_unlock(clock->lock);
132     //DEBUG("gst_clock: 0x%p waiting for time %llu %llu %lld %llu\n", obj, time, target, diff, now);
133     select(0, NULL, NULL, NULL, &tfnow);
134     //DEBUG("gst_clock: 0x%p waiting done time %llu %llu\n", obj, time, target);
135     g_mutex_lock(clock->lock);
136   }
137  // clock->current_time = clock->start_time + time;
138   g_mutex_unlock(clock->lock);
139   //gst_clock_set(clock, time);
140
141 }