Release 970824
[wine] / multimedia / time.c
1 /*
2  * MMSYTEM time functions
3  *
4  * Copyright 1993 Martin Ayotte
5  */
6
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
21 static BOOL32 mmTimeStarted = FALSE;
22 static MMTIME mmSysTimeMS;
23 static MMTIME mmSysTimeSMPTE;
24
25 typedef struct tagTIMERENTRY {
26     WORD wDelay;
27     WORD wResol;
28     FARPROC16 lpFunc;
29     HINSTANCE16 hInstance;
30     DWORD dwUser;
31     WORD wFlags;
32     WORD wTimerID;
33     WORD wCurTime;
34     struct tagTIMERENTRY *Next;
35     struct tagTIMERENTRY *Prev;
36 } TIMERENTRY, *LPTIMERENTRY;
37
38 static LPTIMERENTRY lpTimerList = NULL;
39
40 /*
41  * FIXME
42  * is this the minimum resolution ? 
43  */
44 #define MMSYSTIME_MININTERVAL (33)
45 #define MMSYSTIME_MAXINTERVAL (65535)
46
47
48 /**************************************************************************
49  *           TIME_MMSysTimeCallback
50  */
51 static VOID TIME_MMSysTimeCallback( HWND32 hwnd, UINT32 msg,
52                                     UINT32 id, DWORD dwTime )
53 {
54     LPTIMERENTRY lpTimer = lpTimerList;
55     mmSysTimeMS.u.ms += MMSYSTIME_MININTERVAL;
56     mmSysTimeSMPTE.u.smpte.frame++;
57     while (lpTimer != NULL) {
58         lpTimer->wCurTime--;
59         if (lpTimer->wCurTime == 0) {
60             lpTimer->wCurTime = lpTimer->wDelay;
61             if (lpTimer->lpFunc != (FARPROC16) NULL) {
62                 dprintf_mmtime(stddeb, "MMSysTimeCallback // before CallBack16 !\n");
63                 dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%p wTimerID=%04X dwUser=%08lX !\n",
64                         lpTimer->lpFunc, lpTimer->wTimerID, lpTimer->dwUser);
65                 dprintf_mmtime(stddeb, "MMSysTimeCallback // hInstance=%04X !\n", lpTimer->hInstance);
66
67 /* This is wrong (lpFunc is NULL all the time)
68
69                 lpFunc = MODULE_GetEntryPoint( lpTimer->hInstance,
70                          MODULE_GetOrdinal(lpTimer->hInstance,"TimerCallBack" ));
71                 dprintf_mmtime(stddeb, "MMSysTimeCallback // lpFunc=%08lx !\n", lpFunc);
72 */
73
74
75 /*        - TimeProc callback that is called here is something strange, under Windows 3.1x it is called 
76  *          during interrupt time,  is allowed to execute very limited number of API calls (like
77  *          PostMessage), and must reside in DLL (therefore uses stack of active application). So I 
78  *          guess current implementation via SetTimer has to be improved upon.          
79  */
80
81                 CallTimeFuncProc(lpTimer->lpFunc, lpTimer->wTimerID, 
82                                     0, lpTimer->dwUser, 0, 0);
83
84                 dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
85                 fflush(stdout);
86             }
87             if (lpTimer->wFlags & TIME_ONESHOT)
88                 timeKillEvent(lpTimer->wTimerID);
89         }
90         lpTimer = lpTimer->Next;
91     }
92 }
93
94 /**************************************************************************
95  *                              StartMMTime                     [internal]
96  */
97 static void StartMMTime()
98 {
99     if (!mmTimeStarted) {
100         mmTimeStarted = TRUE;
101         mmSysTimeMS.wType = TIME_MS;
102         mmSysTimeMS.u.ms = 0;
103         mmSysTimeSMPTE.wType = TIME_SMPTE;
104         mmSysTimeSMPTE.u.smpte.hour = 0;
105         mmSysTimeSMPTE.u.smpte.min = 0;
106         mmSysTimeSMPTE.u.smpte.sec = 0;
107         mmSysTimeSMPTE.u.smpte.frame = 0;
108         mmSysTimeSMPTE.u.smpte.fps = 0;
109         mmSysTimeSMPTE.u.smpte.dummy = 0;
110         SetTimer32( 0, 1, MMSYSTIME_MININTERVAL, TIME_MMSysTimeCallback );
111     }
112 }
113
114 /**************************************************************************
115  *                              timeGetSystemTime       [MMSYSTEM.601]
116  */
117 WORD WINAPI timeGetSystemTime(LPMMTIME lpTime, WORD wSize)
118 {
119     dprintf_mmsys(stddeb, "timeGetSystemTime(%p, %u);\n", lpTime, wSize);
120     if (!mmTimeStarted)
121         StartMMTime();
122     lpTime->wType = TIME_MS;
123     lpTime->u.ms = mmSysTimeMS.u.ms;
124     return 0;
125 }
126
127 /**************************************************************************
128  *                              timeSetEvent            [MMSYSTEM.602]
129  */
130 WORD WINAPI timeSetEvent(WORD wDelay, WORD wResol, LPTIMECALLBACK lpFunc,
131                          DWORD dwUser, WORD wFlags)
132 {
133     WORD wNewID = 0;
134     LPTIMERENTRY lpNewTimer;
135     LPTIMERENTRY lpTimer = lpTimerList;
136     dprintf_mmtime(stddeb, "timeSetEvent(%u, %u, %p, %08lX, %04X);\n",
137                   wDelay, wResol, lpFunc, dwUser, wFlags);
138     if (!mmTimeStarted)
139         StartMMTime();
140     lpNewTimer = (LPTIMERENTRY) malloc(sizeof(TIMERENTRY));
141     if (lpNewTimer == NULL)
142         return 0;
143     while (lpTimer != NULL) {
144         wNewID = MAX(wNewID, lpTimer->wTimerID);
145         if (lpTimer->Next == NULL)
146             break;
147         lpTimer = lpTimer->Next;
148     }
149     if (lpTimerList == NULL) {
150         lpTimerList = lpNewTimer;
151         lpNewTimer->Prev = NULL;
152     } else {
153         lpTimer->Next = lpNewTimer;
154         lpNewTimer->Prev = lpTimer;
155     }
156     lpNewTimer->Next = NULL;
157     lpNewTimer->wTimerID = wNewID + 1;
158     lpNewTimer->wCurTime = wDelay;
159     lpNewTimer->wDelay = wDelay;
160     lpNewTimer->wResol = wResol;
161     lpNewTimer->lpFunc = (FARPROC16) lpFunc;
162     lpNewTimer->hInstance = GetTaskDS();
163         dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
164         dprintf_mmtime(stddeb, "timeSetEvent // PTR_SEG_TO_LIN(lpFunc)=%p !\n", 
165                                 PTR_SEG_TO_LIN(lpFunc));
166     lpNewTimer->dwUser = dwUser;
167     lpNewTimer->wFlags = wFlags;
168     return lpNewTimer->wTimerID;
169 }
170
171 /**************************************************************************
172  *                              timeKillEvent           [MMSYSTEM.603]
173  */
174 WORD WINAPI timeKillEvent(WORD wID)
175 {
176     LPTIMERENTRY lpTimer = lpTimerList;
177     while (lpTimer != NULL) {
178         if (wID == lpTimer->wTimerID) {
179             if (lpTimer->Prev != NULL)
180                 lpTimer->Prev->Next = lpTimer->Next;
181             if (lpTimer->Next != NULL)
182                 lpTimer->Next->Prev = lpTimer->Prev;
183             free(lpTimer);
184             if (lpTimer==lpTimerList)
185                 lpTimerList=NULL;
186             return TRUE;
187         }
188         lpTimer = lpTimer->Next;
189     }
190     return 0;
191 }
192
193 /**************************************************************************
194  *                              timeGetDevCaps          [MMSYSTEM.604]
195  */
196 WORD WINAPI timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
197 {
198     dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
199     if (!mmTimeStarted)
200         StartMMTime();
201     lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
202     lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
203     return 0;
204 }
205
206 /**************************************************************************
207  *                              timeBeginPeriod         [MMSYSTEM.605]
208  */
209 WORD WINAPI timeBeginPeriod(WORD wPeriod)
210 {
211     dprintf_mmtime(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
212     if (!mmTimeStarted)
213         StartMMTime();
214     if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
215         return TIMERR_NOCANDO;
216     return 0;
217 }
218
219 /**************************************************************************
220  *                              timeEndPeriod           [MMSYSTEM.606]
221  */
222 WORD WINAPI timeEndPeriod(WORD wPeriod)
223 {
224     dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
225     if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
226         return TIMERR_NOCANDO;
227     return 0;
228 }
229
230 /**************************************************************************
231  *                              timeGetTime             [MMSYSTEM.607]
232  */
233 DWORD WINAPI timeGetTime()
234 {
235     dprintf_mmtime(stddeb, "timeGetTime(); !\n");
236     if (!mmTimeStarted)
237         StartMMTime();
238     dprintf_mmtime(stddeb, "timeGetTime() // Time = %ld\n",mmSysTimeMS.u.ms);
239     return mmSysTimeMS.u.ms;
240 }