Committing in .
[wxWidgets.git] / src / common / timercmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/timercmn.cpp
3 // Purpose: Common timer implementation
4 // Author:
5 // Original version by Julian Smart
6 // Vadim Zeitlin got rid of all ifdefs (11.12.99)
7 // Sylvain Bougnoux added wxStopWatch class
8 // Guillermo Rodriguez <guille@iies.es> rewrote from scratch (Dic/99)
9 // Modified by:
10 // Created: 04/01/98
11 // RCS-ID: $Id$
12 // Copyright: (c) Julian Smart and Markus Holzem
13 // (c) 1999 Guillermo Rodriguez <guille@iies.es>
14 // Licence: wxWindows license
15 /////////////////////////////////////////////////////////////////////////////
16
17 // ============================================================================
18 // declarations
19 // ============================================================================
20
21 // ----------------------------------------------------------------------------
22 // headers
23 // ----------------------------------------------------------------------------
24
25 #ifdef __GNUG__
26 #pragma implementation "timerbase.h"
27 #endif
28
29 // For compilers that support precompilation, includes "wx.h".
30 #include "wx/wxprec.h"
31
32 #ifdef __BORLANDC__
33 #pragma hdrstop
34 #endif
35
36 #ifndef WX_PRECOMP
37 #include "wx/intl.h"
38 #include "wx/log.h"
39 #endif
40
41 #include "wx/timer.h"
42 #include "wx/longlong.h"
43
44 #if defined(__WIN32__)
45 #include <windows.h>
46 #endif
47
48 #include <time.h>
49 #ifndef __WXMAC__
50 #include <sys/types.h> // for time_t
51 #endif
52
53 #if defined(HAVE_GETTIMEOFDAY)
54 #include <sys/time.h>
55 #include <unistd.h>
56 #elif defined(HAVE_FTIME)
57 #include <sys/timeb.h>
58 #endif
59
60 // ----------------------------------------------------------------------------
61 // wxWin macros
62 // ----------------------------------------------------------------------------
63
64 #if wxUSE_GUI
65 IMPLEMENT_DYNAMIC_CLASS(wxTimerEvent, wxEvent)
66 #endif // wxUSE_GUI
67
68 // ----------------------------------------------------------------------------
69 // macros
70 // ----------------------------------------------------------------------------
71
72 // on some really old systems gettimeofday() doesn't have the second argument,
73 // define wxGetTimeOfDay() to hide this difference
74 #ifdef HAVE_GETTIMEOFDAY
75 #ifdef WX_GETTIMEOFDAY_NO_TZ
76 struct timezone;
77 #define wxGetTimeOfDay(tv, tz) gettimeofday(tv)
78 #else
79 #define wxGetTimeOfDay(tv, tz) gettimeofday((tv), (tz))
80 #endif
81 #endif // HAVE_GETTIMEOFDAY
82
83 // ----------------------------------------------------------------------------
84 // prototypes
85 // ----------------------------------------------------------------------------
86
87 wxLongLong wxGetLocalTimeMillis();
88
89 // ============================================================================
90 // implementation
91 // ============================================================================
92
93 #if wxUSE_GUI
94
95 // ----------------------------------------------------------------------------
96 // wxTimerBase
97 // ----------------------------------------------------------------------------
98
99 void wxTimerBase::Notify()
100 {
101 // the base class version generates an event if it has owner - which it
102 // should because otherwise nobody can process timer events
103 wxCHECK_RET( m_owner, _T("wxTimer::Notify() should be overridden.") );
104
105 wxTimerEvent event(m_idTimer, m_milli);
106 (void)m_owner->ProcessEvent(event);
107 }
108
109 #endif // wxUSE_GUI
110
111 // ----------------------------------------------------------------------------
112 // wxStopWatch
113 // ----------------------------------------------------------------------------
114
115 void wxStopWatch::Start(long t)
116 {
117 m_t0 = wxGetLocalTimeMillis() - t;
118 m_pause = 0;
119 }
120
121 long wxStopWatch::GetElapsedTime() const
122 {
123 return (wxGetLocalTimeMillis() - m_t0).GetLo();
124 }
125
126 long wxStopWatch::Time() const
127 {
128 return (m_pause ? m_pause : GetElapsedTime());
129 }
130
131 // ----------------------------------------------------------------------------
132 // old timer functions superceded by wxStopWatch
133 // ----------------------------------------------------------------------------
134
135 static wxLongLong wxStartTime = 0l;
136
137 // starts the global timer
138 void wxStartTimer()
139 {
140 wxStartTime = wxGetLocalTimeMillis();
141 }
142
143 // Returns elapsed time in milliseconds
144 long wxGetElapsedTime(bool resetTimer)
145 {
146 wxLongLong oldTime = wxStartTime;
147 wxLongLong newTime = wxGetLocalTimeMillis();
148
149 if ( resetTimer )
150 wxStartTime = newTime;
151
152 return (newTime - oldTime).GetLo();
153 }
154
155
156 // ----------------------------------------------------------------------------
157 // the functions to get the current time and timezone info
158 // ----------------------------------------------------------------------------
159
160 // Get local time as seconds since 00:00:00, Jan 1st 1970
161 long wxGetLocalTime()
162 {
163 struct tm tm;
164 time_t t0, t1;
165
166 // This cannot be made static because mktime can overwrite it.
167 //
168 memset(&tm, 0, sizeof(tm));
169 tm.tm_year = 70;
170 tm.tm_mon = 0;
171 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
172 tm.tm_hour = 0;
173 tm.tm_min = 0;
174 tm.tm_sec = 0;
175 tm.tm_isdst = -1; // let mktime guess
176
177 // Note that mktime assumes that the struct tm contains local time.
178 //
179 t1 = time(&t1); // now
180 t0 = mktime(&tm); // origin
181
182 // Return the difference in seconds.
183 //
184 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
185 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
186
187 wxLogSysError(_("Failed to get the local system time"));
188 return -1;
189 }
190
191 // Get UTC time as seconds since 00:00:00, Jan 1st 1970
192 long wxGetUTCTime()
193 {
194 struct tm tm, *ptm;
195 time_t t0, t1;
196
197 // This cannot be made static because mktime can overwrite it
198 //
199 memset(&tm, 0, sizeof(tm));
200 tm.tm_year = 70;
201 tm.tm_mon = 0;
202 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
203 tm.tm_hour = 0;
204 tm.tm_min = 0;
205 tm.tm_sec = 0;
206 tm.tm_isdst = -1; // let mktime guess
207
208 // Note that mktime assumes that the struct tm contains local time.
209 //
210 t1 = time(&t1); // now
211 t0 = mktime(&tm); // origin in localtime
212
213 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
214 {
215 // To get t0 as GMT we convert to a struct tm with gmtime,
216 // and then back again.
217 //
218 ptm = gmtime(&t0);
219
220 if (ptm)
221 {
222 memcpy(&tm, ptm, sizeof(tm));
223 t0 = mktime(&tm);
224
225 if (t0 != (time_t)-1 )
226 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
227 wxLogSysError(_("Failed 2nd mktime"));
228 }
229 wxLogSysError(_("Failed gmtime"));
230 }
231 wxLogSysError(_("Failed to get the UTC system time"));
232 return -1;
233 }
234
235
236 // Get local time as milliseconds since 00:00:00, Jan 1st 1970
237 wxLongLong wxGetLocalTimeMillis()
238 {
239 wxLongLong val = 1000l;
240
241 // If possible, use a functin which avoids conversions from
242 // broken-up time structures to milliseconds,
243
244 #if defined(HAVE_GETTIMEOFDAY)
245 struct timeval tp;
246 if ( wxGetTimeOfDay(&tp, (struct timezone *)NULL) != -1 )
247 {
248 val *= tp.tv_sec;
249 return (val + (tp.tv_usec / 1000));
250 }
251 return 0;
252 #elif defined(HAVE_FTIME)
253 struct timeb tp;
254 if ( ftime(&tp) == 0 )
255 {
256 val *= tp.time;
257 return (val + tp.millitm);
258 }
259 #else
260 // We use wxGetLocalTime() to get the seconds since
261 // 00:00:00 Jan 1st 1970 and then whatever is available
262 // to get millisecond resolution.
263 //
264 // TODO: This might lead to a problem if the clocks use
265 // different sources.
266
267 val *= wxGetLocalTime();
268
269 #if defined (__WIN32__)
270 SYSTEMTIME st;
271 ::GetLocalTime(&st);
272 val += st.wMilliseconds;
273 #elif defined(__VISAGECPP__)
274 DATETIME dt;
275 ::DosGetDateTime(&dt);
276 val += (dt.hundredths*10);
277 #else
278 #warning "wxStopWatch will be up to second resolution!"
279 #endif
280
281 return val;
282
283 #endif
284 }