Release 980201
[wine/multimedia.git] / multimedia / time.c
blob5a6d267aeae0d936ea935f9d4bfbe748cc4c3786
1 /*
2 * MMSYTEM time functions
4 * Copyright 1993 Martin Ayotte
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "win.h"
12 #include "ldt.h"
13 #include "module.h"
14 #include "callback.h"
15 #include "user.h"
16 #include "driver.h"
17 #include "mmsystem.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "xmalloc.h"
22 static BOOL32 mmTimeStarted = FALSE;
23 static MMTIME16 mmSysTimeMS;
24 static MMTIME16 mmSysTimeSMPTE;
26 typedef struct tagTIMERENTRY {
27 UINT32 wDelay;
28 UINT32 wResol;
29 FARPROC16 lpFunc;
30 HINSTANCE32 hInstance;
31 DWORD dwUser;
32 UINT32 wFlags;
33 UINT32 wTimerID;
34 UINT32 wCurTime;
35 UINT32 iswin32;
36 struct tagTIMERENTRY *Next;
37 DWORD triggertime;
38 } TIMERENTRY, *LPTIMERENTRY;
40 static LPTIMERENTRY lpTimerList = NULL;
43 * FIXME
44 * is this the minimum resolution ?
46 /*#define MMSYSTIME_MININTERVAL (33)*/
47 #define MMSYSTIME_MININTERVAL (31)
48 #define MMSYSTIME_MAXINTERVAL (65535)
51 /**************************************************************************
52 * check_MMtimers
54 static VOID check_MMtimers()
56 LPTIMERENTRY lpTimer = lpTimerList;
57 DWORD curtick = GetTickCount();
59 while (lpTimer != NULL) {
60 if (lpTimer->triggertime <= curtick) {
61 lpTimer->wCurTime = lpTimer->wDelay;
63 if (lpTimer->lpFunc != (FARPROC16) NULL) {
64 dprintf_mmtime(stddeb, "MMSysTimeCallback // before CallBack16 !\n");
65 dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%p wTimerID=%04X dwUser=%08lX !\n",
66 lpTimer->lpFunc, lpTimer->wTimerID, lpTimer->dwUser);
67 dprintf_mmtime(stddeb, "MMSysTimeCallback // hInstance=%04X !\n", lpTimer->hInstance);
70 /* - TimeProc callback that is called here is something strange, under Windows 3.1x it is called
71 * during interrupt time, is allowed to execute very limited number of API calls (like
72 * PostMessage), and must reside in DLL (therefore uses stack of active application). So I
73 * guess current implementation via SetTimer has to be improved upon.
75 if (lpTimer->iswin32)
76 lpTimer->lpFunc(lpTimer->wTimerID,0,lpTimer->dwUser,0,0);
77 else
78 Callbacks->CallTimeFuncProc(lpTimer->lpFunc,
79 lpTimer->wTimerID,0,
80 lpTimer->dwUser,0,0
83 dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
85 if (lpTimer->wFlags & TIME_ONESHOT)
86 timeKillEvent32(lpTimer->wTimerID);
88 lpTimer = lpTimer->Next;
92 /**************************************************************************
93 * TIME_MMSysTimeCallback
95 static VOID TIME_MMSysTimeCallback( HWND32 hwnd, UINT32 msg,
96 UINT32 id, DWORD dwTime )
98 LPTIMERENTRY lpTimer = lpTimerList;
99 mmSysTimeMS.u.ms += MMSYSTIME_MININTERVAL;
100 mmSysTimeSMPTE.u.smpte.frame++;
101 while (lpTimer != NULL) {
102 lpTimer->wCurTime--;
103 if (lpTimer->wCurTime == 0) {
104 lpTimer->wCurTime = lpTimer->wDelay;
106 if (lpTimer->lpFunc != (FARPROC16) NULL) {
107 dprintf_mmtime(stddeb, "MMSysTimeCallback // before CallBack16 !\n");
108 dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%p wTimerID=%04X dwUser=%08lX !\n",
109 lpTimer->lpFunc, lpTimer->wTimerID, lpTimer->dwUser);
110 dprintf_mmtime(stddeb, "MMSysTimeCallback // hInstance=%04X !\n", lpTimer->hInstance);
112 /* This is wrong (lpFunc is NULL all the time)
114 lpFunc = MODULE_GetEntryPoint( lpTimer->hInstance,
115 MODULE_GetOrdinal(lpTimer->hInstance,"TimerCallBack" ));
116 dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%08lx !\n", lpFunc);
120 /* - TimeProc callback that is called here is something strange, under Windows 3.1x it is called
121 * during interrupt time, is allowed to execute very limited number of API calls (like
122 * PostMessage), and must reside in DLL (therefore uses stack of active application). So I
123 * guess current implementation via SetTimer has to be improved upon.
125 if (lpTimer->iswin32)
126 lpTimer->lpFunc(lpTimer->wTimerID,0,lpTimer->dwUser,0,0);
127 else
128 Callbacks->CallTimeFuncProc(lpTimer->lpFunc,
129 lpTimer->wTimerID,0,
130 lpTimer->dwUser,0,0
133 dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
134 fflush(stdout);
136 if (lpTimer->wFlags & TIME_ONESHOT)
137 timeKillEvent32(lpTimer->wTimerID);
139 lpTimer = lpTimer->Next;
143 /**************************************************************************
144 * StartMMTime [internal]
146 static void StartMMTime()
148 if (!mmTimeStarted) {
149 mmTimeStarted = TRUE;
150 mmSysTimeMS.wType = TIME_MS;
151 mmSysTimeMS.u.ms = 0;
152 mmSysTimeSMPTE.wType = TIME_SMPTE;
153 mmSysTimeSMPTE.u.smpte.hour = 0;
154 mmSysTimeSMPTE.u.smpte.min = 0;
155 mmSysTimeSMPTE.u.smpte.sec = 0;
156 mmSysTimeSMPTE.u.smpte.frame = 0;
157 mmSysTimeSMPTE.u.smpte.fps = 0;
158 mmSysTimeSMPTE.u.smpte.dummy = 0;
159 SetTimer32( 0, 1, MMSYSTIME_MININTERVAL, TIME_MMSysTimeCallback );
163 /**************************************************************************
164 * timeGetSystemTime [WINMM.140]
166 MMRESULT32 WINAPI timeGetSystemTime32(LPMMTIME32 lpTime, UINT32 wSize)
168 dprintf_mmsys(stddeb, "timeGetSystemTime32(%p, %u);\n", lpTime, wSize);
169 if (!mmTimeStarted)
170 StartMMTime();
171 lpTime->wType = TIME_MS;
172 lpTime->u.ms = mmSysTimeMS.u.ms;
173 return 0;
176 /**************************************************************************
177 * timeGetSystemTime [MMSYSTEM.601]
179 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
181 dprintf_mmsys(stddeb, "timeGetSystemTime16(%p, %u);\n", lpTime, wSize);
182 if (!mmTimeStarted)
183 StartMMTime();
184 lpTime->wType = TIME_MS;
185 lpTime->u.ms = mmSysTimeMS.u.ms;
186 return 0;
189 /**************************************************************************
190 * timeSetEvent [MMSYSTEM.602]
192 MMRESULT32 WINAPI timeSetEvent32(UINT32 wDelay,UINT32 wResol,
193 LPTIMECALLBACK32 lpFunc,DWORD dwUser,
194 UINT32 wFlags)
196 WORD wNewID = 0;
197 LPTIMERENTRY lpNewTimer;
198 LPTIMERENTRY lpTimer = lpTimerList;
200 dprintf_mmtime(stddeb, "timeSetEvent32(%u, %u, %p, %08lX, %04X);\n",
201 wDelay, wResol, lpFunc, dwUser, wFlags);
202 if (!mmTimeStarted)
203 StartMMTime();
204 lpNewTimer = (LPTIMERENTRY)xmalloc(sizeof(TIMERENTRY));
205 if (lpNewTimer == NULL)
206 return 0;
207 while (lpTimer != NULL) {
208 wNewID = MAX(wNewID, lpTimer->wTimerID);
209 lpTimer = lpTimer->Next;
212 lpNewTimer->Next = lpTimerList;
213 lpTimerList = lpNewTimer;
214 lpNewTimer->wTimerID = wNewID + 1;
215 lpNewTimer->wCurTime = wDelay;
216 lpNewTimer->triggertime = wDelay+GetTickCount();
217 lpNewTimer->wDelay = wDelay;
218 lpNewTimer->wResol = wResol;
219 lpNewTimer->lpFunc = (FARPROC16) lpFunc;
220 lpNewTimer->iswin32 = 1;
221 lpNewTimer->hInstance = GetTaskDS();
222 dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
223 dprintf_mmtime(stddeb, "timeSetEvent // lpFunc=%p !\n",
224 lpFunc);
225 lpNewTimer->dwUser = dwUser;
226 lpNewTimer->wFlags = wFlags;
227 return lpNewTimer->wTimerID;
230 /**************************************************************************
231 * timeSetEvent [MMSYSTEM.602]
233 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol,
234 LPTIMECALLBACK16 lpFunc,DWORD dwUser,
235 UINT16 wFlags)
237 WORD wNewID = 0;
238 LPTIMERENTRY lpNewTimer;
239 LPTIMERENTRY lpTimer = lpTimerList;
240 dprintf_mmtime(stddeb, "timeSetEvent(%u, %u, %p, %08lX, %04X);\n",
241 wDelay, wResol, lpFunc, dwUser, wFlags);
242 if (!mmTimeStarted)
243 StartMMTime();
244 lpNewTimer = (LPTIMERENTRY)xmalloc(sizeof(TIMERENTRY));
245 if (lpNewTimer == NULL)
246 return 0;
247 while (lpTimer != NULL) {
248 wNewID = MAX(wNewID, lpTimer->wTimerID);
249 lpTimer = lpTimer->Next;
252 lpNewTimer->Next = lpTimerList;
253 lpTimerList = lpNewTimer;
254 lpNewTimer->wTimerID = wNewID + 1;
255 lpNewTimer->wCurTime = wDelay;
256 lpNewTimer->wDelay = wDelay;
257 lpNewTimer->triggertime = wDelay+GetTickCount();
258 lpNewTimer->wResol = wResol;
259 lpNewTimer->lpFunc = (FARPROC16) lpFunc;
260 lpNewTimer->iswin32 = 0;
261 lpNewTimer->hInstance = GetTaskDS();
262 dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
263 dprintf_mmtime(stddeb, "timeSetEvent // PTR_SEG_TO_LIN(lpFunc)=%p !\n",
264 PTR_SEG_TO_LIN(lpFunc));
265 lpNewTimer->dwUser = dwUser;
266 lpNewTimer->wFlags = wFlags;
267 return lpNewTimer->wTimerID;
270 /**************************************************************************
271 * timeKillEvent [WINMM.142]
273 MMRESULT32 WINAPI timeKillEvent32(UINT32 wID)
275 LPTIMERENTRY xlptimer,*lpTimer = &lpTimerList;
276 while (*lpTimer) {
277 if (wID == (*lpTimer)->wTimerID) {
278 xlptimer = (*lpTimer)->Next;
279 free(*lpTimer);
280 *lpTimer = xlptimer;
281 return TRUE;
283 lpTimer = &((*lpTimer)->Next);
285 return 0;
288 /**************************************************************************
289 * timeKillEvent [MMSYSTEM.603]
291 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
293 return timeKillEvent32(wID);
296 /**************************************************************************
297 * timeGetDevCaps [WINMM.139]
299 MMRESULT32 WINAPI timeGetDevCaps32(LPTIMECAPS32 lpCaps,UINT32 wSize)
301 dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
302 if (!mmTimeStarted)
303 StartMMTime();
304 lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
305 lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
306 return 0;
309 /**************************************************************************
310 * timeGetDevCaps [MMSYSTEM.604]
312 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
314 dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
315 if (!mmTimeStarted)
316 StartMMTime();
317 lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
318 lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
319 return 0;
322 /**************************************************************************
323 * timeBeginPeriod [WINMM.137]
325 MMRESULT32 WINAPI timeBeginPeriod32(UINT32 wPeriod)
327 dprintf_mmtime(stddeb, "timeBeginPeriod32(%u) !\n", wPeriod);
328 if (!mmTimeStarted)
329 StartMMTime();
330 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
331 return TIMERR_NOCANDO;
332 return 0;
334 /**************************************************************************
335 * timeBeginPeriod [MMSYSTEM.605]
337 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
339 dprintf_mmtime(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
340 if (!mmTimeStarted)
341 StartMMTime();
342 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
343 return TIMERR_NOCANDO;
344 return 0;
347 /**************************************************************************
348 * timeEndPeriod [WINMM.138]
350 MMRESULT32 WINAPI timeEndPeriod32(UINT32 wPeriod)
352 dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
353 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
354 return TIMERR_NOCANDO;
355 return 0;
358 /**************************************************************************
359 * timeEndPeriod [MMSYSTEM.606]
361 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
363 dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
364 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
365 return TIMERR_NOCANDO;
366 return 0;
369 /**************************************************************************
370 * timeGetTime [MMSYSTEM.607][WINMM.141]
372 DWORD WINAPI timeGetTime()
374 static DWORD lasttick=0;
375 DWORD newtick;
377 dprintf_mmtime(stddeb, "timeGetTime(); !\n");
378 if (!mmTimeStarted)
379 StartMMTime();
380 newtick = GetTickCount();
381 mmSysTimeMS.u.ms+=newtick-lasttick; /* FIXME: faked timer */
382 if (newtick!=lasttick)
383 check_MMtimers();
384 lasttick = newtick;
385 dprintf_mmtime(stddeb, "timeGetTime() // Time = %ld\n",mmSysTimeMS.u.ms);
388 return mmSysTimeMS.u.ms;