1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * MMSYTEM time functions
6 * Copyright 1993 Martin Ayotte
13 #include "wine/winbase16.h" /* GetTaskDS */
19 #include "debugtools.h"
21 DECLARE_DEBUG_CHANNEL(mmsys)
22 DECLARE_DEBUG_CHANNEL(mmtime)
24 static MMTIME16 mmSysTimeMS;
25 static MMTIME16 mmSysTimeSMPTE;
27 typedef struct tagTIMERENTRY {
37 struct tagTIMERENTRY* Next;
38 } TIMERENTRY, *LPTIMERENTRY;
40 static LPTIMERENTRY lpTimerList = NULL;
41 static HANDLE hMMTimer;
45 * We're using "1" as the mininum resolution to the timer,
46 * as Windows 95 does, according to the docs. Maybe it should
47 * depend on the computers resources!
49 #define MMSYSTIME_MININTERVAL /* (1) */ (10)
50 #define MMSYSTIME_MAXINTERVAL (65535)
52 static void TIME_TriggerCallBack(LPTIMERENTRY lpTimer, DWORD dwCurrent)
54 lpTimer->wCurTime = lpTimer->wDelay;
56 if (lpTimer->lpFunc != (FARPROC16) NULL) {
57 TRACE_(mmtime)("before CallBack16 (%lu)!\n", dwCurrent);
58 TRACE_(mmtime)("lpFunc=%p wTimerID=%04X dwUser=%08lX !\n",
59 lpTimer->lpFunc, lpTimer->wTimerID, lpTimer->dwUser);
60 TRACE_(mmtime)("hInstance=%04X !\n", lpTimer->hInstance);
63 /* - TimeProc callback that is called here is something strange, under Windows 3.1x it is called
64 * during interrupt time, is allowed to execute very limited number of API calls (like
65 * PostMessage), and must reside in DLL (therefore uses stack of active application). So I
66 * guess current implementation via SetTimer has to be improved upon.
68 switch (lpTimer->wFlags & 0x30) {
69 case TIME_CALLBACK_FUNCTION:
71 lpTimer->lpFunc(lpTimer->wTimerID,0,lpTimer->dwUser,0,0);
73 Callbacks->CallTimeFuncProc(lpTimer->lpFunc,
77 case TIME_CALLBACK_EVENT_SET:
78 SetEvent((HANDLE)lpTimer->lpFunc);
80 case TIME_CALLBACK_EVENT_PULSE:
81 PulseEvent((HANDLE)lpTimer->lpFunc);
84 FIXME_(mmtime)("Unknown callback type 0x%04x for mmtime callback (%p),ignored.\n",lpTimer->wFlags,lpTimer->lpFunc);
87 TRACE_(mmtime)("after CallBack16 !\n");
89 if (lpTimer->wFlags & TIME_ONESHOT)
90 timeKillEvent(lpTimer->wTimerID);
93 /**************************************************************************
94 * TIME_MMSysTimeCallback
96 static VOID CALLBACK TIME_MMSysTimeCallback( ULONG_PTR dummy )
100 mmSysTimeMS.u.ms += MMSYSTIME_MININTERVAL;
101 mmSysTimeSMPTE.u.smpte.frame++;
103 for (lpTimer = lpTimerList; lpTimer != NULL; lpTimer = lpTimer->Next) {
104 if (lpTimer->wCurTime < MMSYSTIME_MININTERVAL) {
105 TIME_TriggerCallBack(lpTimer, mmSysTimeMS.u.ms);
107 lpTimer->wCurTime -= MMSYSTIME_MININTERVAL;
112 /**************************************************************************
113 * StartMMTime [internal]
115 static void StartMMTime()
117 static BOOL mmTimeStarted = FALSE;
119 if (!mmTimeStarted) {
120 mmTimeStarted = TRUE;
121 mmSysTimeMS.wType = TIME_MS;
122 mmSysTimeMS.u.ms = GetTickCount();
123 mmSysTimeSMPTE.wType = TIME_SMPTE;
124 mmSysTimeSMPTE.u.smpte.hour = 0;
125 mmSysTimeSMPTE.u.smpte.min = 0;
126 mmSysTimeSMPTE.u.smpte.sec = 0;
127 mmSysTimeSMPTE.u.smpte.frame = 0;
128 mmSysTimeSMPTE.u.smpte.fps = 0;
129 mmSysTimeSMPTE.u.smpte.dummy = 0;
130 hMMTimer = SERVICE_AddTimer( MMSYSTIME_MININTERVAL*1000L, TIME_MMSysTimeCallback, 0 );
134 /**************************************************************************
135 * timeGetSystemTime [WINMM.140]
137 MMRESULT WINAPI timeGetSystemTime(LPMMTIME lpTime, UINT wSize)
139 TRACE_(mmsys)("(%p, %u);\n", lpTime, wSize);
141 lpTime->wType = TIME_MS;
142 lpTime->u.ms = mmSysTimeMS.u.ms;
146 /**************************************************************************
147 * timeGetSystemTime [MMSYSTEM.601]
149 MMRESULT16 WINAPI timeGetSystemTime16(LPMMTIME16 lpTime, UINT16 wSize)
151 TRACE_(mmsys)("(%p, %u);\n", lpTime, wSize);
153 lpTime->wType = TIME_MS;
154 lpTime->u.ms = mmSysTimeMS.u.ms;
158 static WORD timeSetEventInternal(UINT wDelay,UINT wResol,
159 FARPROC16 lpFunc,DWORD dwUser,
160 UINT wFlags, UINT16 isWin32)
163 LPTIMERENTRY lpNewTimer;
164 LPTIMERENTRY lpTimer = lpTimerList;
166 TRACE_(mmtime)("(%u, %u, %p, %08lX, %04X);\n",
167 wDelay, wResol, lpFunc, dwUser, wFlags);
169 lpNewTimer = (LPTIMERENTRY)xmalloc(sizeof(TIMERENTRY));
170 if (lpNewTimer == NULL)
172 while (lpTimer != NULL) {
173 wNewID = MAX(wNewID, lpTimer->wTimerID);
174 lpTimer = lpTimer->Next;
177 lpNewTimer->Next = lpTimerList;
178 lpTimerList = lpNewTimer;
179 lpNewTimer->wTimerID = wNewID + 1;
180 lpNewTimer->wCurTime = wDelay;
181 lpNewTimer->wDelay = wDelay;
182 lpNewTimer->wResol = wResol;
183 lpNewTimer->lpFunc = lpFunc;
184 lpNewTimer->isWin32 = isWin32;
185 lpNewTimer->hInstance = GetTaskDS16();
186 TRACE_(mmtime)("hInstance=%04X !\n", lpNewTimer->hInstance);
187 TRACE_(mmtime)("lpFunc=0x%08lx !\n", (DWORD)lpFunc );
188 lpNewTimer->dwUser = dwUser;
189 lpNewTimer->wFlags = wFlags;
190 return lpNewTimer->wTimerID;
193 /**************************************************************************
194 * timeSetEvent [MMSYSTEM.602]
196 MMRESULT WINAPI timeSetEvent(UINT wDelay,UINT wResol,
197 LPTIMECALLBACK lpFunc,DWORD dwUser,
200 return timeSetEventInternal(wDelay, wResol, (FARPROC16)lpFunc,
204 /**************************************************************************
205 * timeSetEvent [MMSYSTEM.602]
207 MMRESULT16 WINAPI timeSetEvent16(UINT16 wDelay, UINT16 wResol,
208 LPTIMECALLBACK16 lpFunc,DWORD dwUser,
211 return timeSetEventInternal(wDelay, wResol, (FARPROC16)lpFunc,
215 /**************************************************************************
216 * timeKillEvent [WINMM.142]
218 MMRESULT WINAPI timeKillEvent(UINT wID)
220 LPTIMERENTRY* lpTimer;
222 for (lpTimer = &lpTimerList; *lpTimer; lpTimer = &((*lpTimer)->Next)) {
223 if (wID == (*lpTimer)->wTimerID) {
224 LPTIMERENTRY xlptimer = (*lpTimer)->Next;
234 /**************************************************************************
235 * timeKillEvent [MMSYSTEM.603]
237 MMRESULT16 WINAPI timeKillEvent16(UINT16 wID)
239 return timeKillEvent(wID);
242 /**************************************************************************
243 * timeGetDevCaps [WINMM.139]
245 MMRESULT WINAPI timeGetDevCaps(LPTIMECAPS lpCaps,UINT wSize)
247 TRACE_(mmtime)("(%p, %u) !\n", lpCaps, wSize);
249 lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
250 lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
254 /**************************************************************************
255 * timeGetDevCaps [MMSYSTEM.604]
257 MMRESULT16 WINAPI timeGetDevCaps16(LPTIMECAPS16 lpCaps, UINT16 wSize)
259 TRACE_(mmtime)("(%p, %u) !\n", lpCaps, wSize);
261 lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
262 lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
266 /**************************************************************************
267 * timeBeginPeriod [WINMM.137]
269 MMRESULT WINAPI timeBeginPeriod(UINT wPeriod)
271 TRACE_(mmtime)("(%u) !\n", wPeriod);
273 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
274 return TIMERR_NOCANDO;
277 /**************************************************************************
278 * timeBeginPeriod [MMSYSTEM.605]
280 MMRESULT16 WINAPI timeBeginPeriod16(UINT16 wPeriod)
282 TRACE_(mmtime)("(%u) !\n", wPeriod);
284 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
285 return TIMERR_NOCANDO;
289 /**************************************************************************
290 * timeEndPeriod [WINMM.138]
292 MMRESULT WINAPI timeEndPeriod(UINT wPeriod)
294 TRACE_(mmtime)("(%u) !\n", wPeriod);
296 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
297 return TIMERR_NOCANDO;
301 /**************************************************************************
302 * timeEndPeriod [MMSYSTEM.606]
304 MMRESULT16 WINAPI timeEndPeriod16(UINT16 wPeriod)
306 TRACE_(mmtime)("(%u) !\n", wPeriod);
307 if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL)
308 return TIMERR_NOCANDO;
312 /**************************************************************************
313 * timeGetTime [MMSYSTEM.607][WINMM.141]
315 DWORD WINAPI timeGetTime()
318 return mmSysTimeMS.u.ms;