Release 971012
[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 #include "xmalloc.h"
21
22 static BOOL32 mmTimeStarted = FALSE;
23 static MMTIME mmSysTimeMS;
24 static MMTIME mmSysTimeSMPTE;
25
26 typedef struct tagTIMERENTRY {
27     WORD wDelay;
28     WORD wResol;
29     FARPROC16 lpFunc;
30     HINSTANCE16 hInstance;
31     DWORD dwUser;
32     WORD wFlags;
33     WORD wTimerID;
34     WORD wCurTime;
35     struct tagTIMERENTRY *Next;
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)xmalloc(sizeof(TIMERENTRY));
141     if (lpNewTimer == NULL)
142         return 0;
143     while (lpTimer != NULL) {
144         wNewID = MAX(wNewID, lpTimer->wTimerID);
145         lpTimer = lpTimer->Next;
146     }
147
148     lpNewTimer->Next = lpTimerList;
149     lpTimerList = lpNewTimer;
150     lpNewTimer->wTimerID = wNewID + 1;
151     lpNewTimer->wCurTime = wDelay;
152     lpNewTimer->wDelay = wDelay;
153     lpNewTimer->wResol = wResol;
154     lpNewTimer->lpFunc = (FARPROC16) lpFunc;
155     lpNewTimer->hInstance = GetTaskDS();
156         dprintf_mmtime(stddeb, "timeSetEvent // hInstance=%04X !\n", lpNewTimer->hInstance);
157         dprintf_mmtime(stddeb, "timeSetEvent // PTR_SEG_TO_LIN(lpFunc)=%p !\n", 
158                                 PTR_SEG_TO_LIN(lpFunc));
159     lpNewTimer->dwUser = dwUser;
160     lpNewTimer->wFlags = wFlags;
161     return lpNewTimer->wTimerID;
162 }
163
164 /**************************************************************************
165  *                              timeKillEvent           [MMSYSTEM.603]
166  */
167 WORD WINAPI timeKillEvent(WORD wID)
168 {
169     LPTIMERENTRY xlptimer,*lpTimer = &lpTimerList;
170     while (*lpTimer) {
171         if (wID == (*lpTimer)->wTimerID) {
172             xlptimer = (*lpTimer)->Next;
173             free(*lpTimer);
174             *lpTimer = xlptimer;
175             return TRUE;
176         }
177         lpTimer = &((*lpTimer)->Next);
178     }
179     return 0;
180 }
181
182 /**************************************************************************
183  *                              timeGetDevCaps          [MMSYSTEM.604]
184  */
185 WORD WINAPI timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
186 {
187     dprintf_mmtime(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
188     if (!mmTimeStarted)
189         StartMMTime();
190     lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL;
191     lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL;
192     return 0;
193 }
194
195 /**************************************************************************
196  *                              timeBeginPeriod         [MMSYSTEM.605]
197  */
198 WORD WINAPI timeBeginPeriod(WORD wPeriod)
199 {
200     dprintf_mmtime(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
201     if (!mmTimeStarted)
202         StartMMTime();
203     if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
204         return TIMERR_NOCANDO;
205     return 0;
206 }
207
208 /**************************************************************************
209  *                              timeEndPeriod           [MMSYSTEM.606]
210  */
211 WORD WINAPI timeEndPeriod(WORD wPeriod)
212 {
213     dprintf_mmtime(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
214     if (wPeriod < MMSYSTIME_MININTERVAL || wPeriod > MMSYSTIME_MAXINTERVAL) 
215         return TIMERR_NOCANDO;
216     return 0;
217 }
218
219 /**************************************************************************
220  *                              timeGetTime             [MMSYSTEM.607]
221  */
222 DWORD WINAPI timeGetTime()
223 {
224     dprintf_mmtime(stddeb, "timeGetTime(); !\n");
225     if (!mmTimeStarted)
226         StartMMTime();
227     dprintf_mmtime(stddeb, "timeGetTime() // Time = %ld\n",mmSysTimeMS.u.ms);
228     return mmSysTimeMS.u.ms;
229 }