Release 980517
[wine] / multimedia / mcianim.c
1 /*
2  * Sample MCI ANIMATION Wine Driver for Linux
3  *
4  * Copyright 1994 Martin Ayotte
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include "windows.h"
14 #include "user.h"
15 #include "driver.h"
16 #include "mmsystem.h"
17 #include "debug.h"
18
19 #define MAX_ANIMDRV             2
20
21 #define ANIMFRAMES_PERSEC       30
22 #define ANIMFRAMES_PERMIN       1800
23 #define SECONDS_PERMIN          60
24
25 typedef struct {
26     int     nUseCount;          /* Incremented for each shared open */
27     BOOL16  fShareable;         /* TRUE if first open was shareable */
28     WORD    wNotifyDeviceID;    /* MCI device ID with a pending notification */
29     HANDLE16 hCallback;          /* Callback handle for pending notification */
30         MCI_OPEN_PARMS16 openParms;
31         DWORD   dwTimeFormat;
32         int             mode;
33         UINT16  nCurTrack;
34         DWORD   dwCurFrame;
35         UINT16  nTracks;
36         DWORD   dwTotalLen;
37         LPDWORD lpdwTrackLen;
38         LPDWORD lpdwTrackPos;
39 } LINUX_ANIM;
40
41 static LINUX_ANIM       AnimDev[MAX_ANIMDRV];
42
43
44 /*-----------------------------------------------------------------------*/
45
46 /**************************************************************************
47 *                               ANIM_mciOpen                    [internal]
48 */
49 static DWORD ANIM_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS16 lpParms)
50 {
51         LPSTR           lpstrElementName;
52         char            str[128];
53
54         TRACE(mcianim,"(%04X, %08lX, %p);\n", 
55                                         wDevID, dwFlags, lpParms);
56         if (lpParms == NULL) return MCIERR_INTERNAL;
57         if (AnimDev[wDevID].nUseCount > 0) {
58                 /* The driver already open on this channel */
59                 /* If the driver was opened shareable before and this open specifies */
60                 /* shareable then increment the use count */
61                 if (AnimDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
62                         ++AnimDev[wDevID].nUseCount;
63                 else
64                         return MCIERR_MUST_USE_SHAREABLE;
65                 }
66         else {
67                 AnimDev[wDevID].nUseCount = 1;
68                 AnimDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
69                 }
70         TRACE(mcianim,"wDevID=%04X\n", wDevID);
71         lpParms->wDeviceID = wDevID;
72         TRACE(mcianim,"lpParms->wDevID=%04X\n", lpParms->wDeviceID);
73     if (dwFlags & MCI_OPEN_ELEMENT) {
74                 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
75                 TRACE(mcianim,"MCI_OPEN_ELEMENT '%s' !\n",
76                                                 lpstrElementName);
77                 if (strlen(lpstrElementName) > 0) {
78                         strcpy(str, lpstrElementName);
79                         CharUpper32A(str);
80                         }
81                 }
82         memcpy(&AnimDev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS16));
83         AnimDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
84         AnimDev[wDevID].mode = 0;
85         AnimDev[wDevID].dwTimeFormat = MCI_FORMAT_TMSF;
86         AnimDev[wDevID].nCurTrack = 0;
87         AnimDev[wDevID].nTracks = 0;
88         AnimDev[wDevID].dwTotalLen = 0;
89         AnimDev[wDevID].lpdwTrackLen = NULL;
90         AnimDev[wDevID].lpdwTrackPos = NULL;
91 /*
92    Moved to mmsystem.c mciOpen routine 
93
94         if (dwFlags & MCI_NOTIFY) {
95                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
96                         lpParms->dwCallback);
97                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
98                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
99                 }
100 */
101         return 0;
102 }
103
104 /**************************************************************************
105 *                               ANIM_mciClose           [internal]
106 */
107 static DWORD ANIM_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
108 {
109         TRACE(mcianim,"(%u, %08lX, %p);\n", 
110                                 wDevID, dwParam, lpParms);
111         if (AnimDev[wDevID].lpdwTrackLen != NULL) free(AnimDev[wDevID].lpdwTrackLen);
112         if (AnimDev[wDevID].lpdwTrackPos != NULL) free(AnimDev[wDevID].lpdwTrackPos);
113         return 0;
114 }
115
116 /**************************************************************************
117 *                               ANIM_mciGetDevCaps      [internal]
118 */
119 static DWORD ANIM_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags, 
120                                                 LPMCI_GETDEVCAPS_PARMS lpParms)
121 {
122         TRACE(mcianim,"(%u, %08lX, %p);\n", 
123                                 wDevID, dwFlags, lpParms);
124         if (lpParms == NULL) return MCIERR_INTERNAL;
125         if (dwFlags & MCI_GETDEVCAPS_ITEM) {
126                 TRACE(mcianim, "MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n",
127                                 lpParms->dwItem);
128                 switch(lpParms->dwItem) {
129                         case MCI_GETDEVCAPS_CAN_RECORD:
130                                 lpParms->dwReturn = FALSE;
131                                 break;
132                         case MCI_GETDEVCAPS_HAS_AUDIO:
133                                 lpParms->dwReturn = FALSE;
134                                 break;
135                         case MCI_GETDEVCAPS_HAS_VIDEO:
136                                 lpParms->dwReturn = FALSE;
137                                 break;
138                         case MCI_GETDEVCAPS_DEVICE_TYPE:
139                                 lpParms->dwReturn = MCI_DEVTYPE_ANIMATION;
140                                 break;
141                         case MCI_GETDEVCAPS_USES_FILES:
142                                 lpParms->dwReturn = TRUE;
143                                 break;
144                         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
145                                 lpParms->dwReturn = FALSE;
146                                 break;
147                         case MCI_GETDEVCAPS_CAN_EJECT:
148                                 lpParms->dwReturn = TRUE;
149                                 break;
150                         case MCI_GETDEVCAPS_CAN_PLAY:
151                                 lpParms->dwReturn = FALSE;
152                                 break;
153                         case MCI_GETDEVCAPS_CAN_SAVE:
154                                 lpParms->dwReturn = FALSE;
155                                 break;
156                         default:
157                                 return MCIERR_UNRECOGNIZED_COMMAND;
158                         }
159                 }
160         TRACE(mcianim, "lpParms->dwReturn=%08lX;\n", 
161                 lpParms->dwReturn);
162         return 0;
163 }
164
165
166 /**************************************************************************
167 *                               ANIM_CalcTime                   [internal]
168 */
169 static DWORD ANIM_CalcTime(UINT16 wDevID, DWORD dwFormatType, DWORD dwFrame)
170 {
171         DWORD   dwTime = 0;
172         UINT16  wTrack;
173         UINT16  wMinutes;
174         UINT16  wSeconds;
175         UINT16  wFrames;
176         TRACE(mcianim,"(%u, %08lX, %lu);\n", 
177                         wDevID, dwFormatType, dwFrame);
178     
179         switch (dwFormatType) {
180                 case MCI_FORMAT_MILLISECONDS:
181                         dwTime = dwFrame / ANIMFRAMES_PERSEC * 1000;
182                         TRACE(mcianim, "MILLISECONDS %lu\n", dwTime);
183                         break;
184                 case MCI_FORMAT_MSF:
185                         wMinutes = dwFrame / ANIMFRAMES_PERMIN;
186                         wSeconds = (dwFrame - ANIMFRAMES_PERMIN * wMinutes) / ANIMFRAMES_PERSEC;
187                         wFrames = dwFrame - ANIMFRAMES_PERMIN * wMinutes - 
188                                                                 ANIMFRAMES_PERSEC * wSeconds;
189                         dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
190                         TRACE(mcianim,"MSF %02u:%02u:%02u -> dwTime=%lu\n",
191                                                                 wMinutes, wSeconds, wFrames, dwTime);
192                         break;
193                 default:
194                         /* unknown format ! force TMSF ! ... */
195                         dwFormatType = MCI_FORMAT_TMSF;
196                 case MCI_FORMAT_TMSF:
197                         for (wTrack = 0; wTrack < AnimDev[wDevID].nTracks; wTrack++) {
198 /*                              dwTime += AnimDev[wDevID].lpdwTrackLen[wTrack - 1];
199                                 TRACE(mcianim, "Adding trk#%u curpos=%u \n", dwTime);
200                                 if (dwTime >= dwFrame) break; */
201                                 if (AnimDev[wDevID].lpdwTrackPos[wTrack - 1] >= dwFrame) break;
202                                 }
203                         wMinutes = dwFrame / ANIMFRAMES_PERMIN;
204                         wSeconds = (dwFrame - ANIMFRAMES_PERMIN * wMinutes) / ANIMFRAMES_PERSEC;
205                         wFrames = dwFrame - ANIMFRAMES_PERMIN * wMinutes - 
206                                                                 ANIMFRAMES_PERSEC * wSeconds;
207                         dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
208                         TRACE(mcianim, "%02u-%02u:%02u:%02u\n",
209                                 wTrack, wMinutes, wSeconds, wFrames);
210                         break;
211                 }
212         return dwTime;
213 }
214
215
216 /**************************************************************************
217 *                               ANIM_CalcFrame                  [internal]
218 */
219 static DWORD ANIM_CalcFrame(UINT16 wDevID, DWORD dwFormatType, DWORD dwTime)
220 {
221         DWORD   dwFrame = 0;
222         UINT16  wTrack;
223         TRACE(mcianim,"(%u, %08lX, %lu);\n", 
224                         wDevID, dwFormatType, dwTime);
225
226         switch (dwFormatType) {
227                 case MCI_FORMAT_MILLISECONDS:
228                         dwFrame = dwTime * ANIMFRAMES_PERSEC / 1000;
229                         TRACE(mcianim, "MILLISECONDS %lu\n", dwFrame);
230                         break;
231                 case MCI_FORMAT_MSF:
232                         TRACE(mcianim, "MSF %02u:%02u:%02u\n",
233                                 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), 
234                                 MCI_MSF_FRAME(dwTime));
235                         dwFrame += ANIMFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
236                         dwFrame += ANIMFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
237                         dwFrame += MCI_MSF_FRAME(dwTime);
238                         break;
239                 default:
240                         /* unknown format ! force TMSF ! ... */
241                         dwFormatType = MCI_FORMAT_TMSF;
242                 case MCI_FORMAT_TMSF:
243                         wTrack = MCI_TMSF_TRACK(dwTime);
244                         TRACE(mcianim, "TMSF %02u-%02u:%02u:%02u\n",
245                                 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), 
246                                 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
247                         TRACE(mcianim, "TMSF trackpos[%u]=%lu\n",
248                                 wTrack, AnimDev[wDevID].lpdwTrackPos[wTrack - 1]);
249                         dwFrame = AnimDev[wDevID].lpdwTrackPos[wTrack - 1];
250                         dwFrame += ANIMFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
251                         dwFrame += ANIMFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
252                         dwFrame += MCI_TMSF_FRAME(dwTime);
253                         break;
254                 }
255         return dwFrame;
256 }
257
258
259 /**************************************************************************
260 *                               ANIM_mciInfo                    [internal]
261 */
262 static DWORD ANIM_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
263 {
264         TRACE(mcianim,"(%u, %08lX, %p);\n", 
265                 wDevID, dwFlags, lpParms);
266         if (lpParms == NULL) return MCIERR_INTERNAL;
267         lpParms->lpstrReturn = NULL;
268         switch(dwFlags) {
269                 case MCI_INFO_PRODUCT:
270                         lpParms->lpstrReturn = "Linux ANIMATION 0.5";
271                         break;
272                 case MCI_INFO_FILE:
273                         lpParms->lpstrReturn = 
274                                 (LPSTR)AnimDev[wDevID].openParms.lpstrElementName;
275                         break;
276                 case MCI_ANIM_INFO_TEXT:
277                         lpParms->lpstrReturn = "Animation Window";
278                         break;
279                 default:
280                         return MCIERR_UNRECOGNIZED_COMMAND;
281                 }
282         if (lpParms->lpstrReturn != NULL)
283                 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
284         else
285                 lpParms->dwRetSize = 0;
286         return 0;
287 }
288
289 /**************************************************************************
290 *                               ANIM_mciStatus          [internal]
291 */
292 static DWORD ANIM_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
293 {
294         TRACE(mcianim,"(%u, %08lX, %p);\n", 
295                         wDevID, dwFlags, lpParms);
296         if (lpParms == NULL) return MCIERR_INTERNAL;
297         if (dwFlags & MCI_NOTIFY) {
298                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
299                         lpParms->dwCallback);
300                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
301                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
302                 }
303         if (dwFlags & MCI_STATUS_ITEM) {
304                 switch(lpParms->dwItem) {
305                         case MCI_STATUS_CURRENT_TRACK:
306                                 lpParms->dwReturn = AnimDev[wDevID].nCurTrack;
307                                 TRACE(mcianim,"CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
308                                 return 0;
309                         case MCI_STATUS_LENGTH:
310                                 if (dwFlags & MCI_TRACK) {
311                                         TRACE(mcianim,"MCI_TRACK #%lu LENGTH=??? !\n",
312                                                                                                                 lpParms->dwTrack);
313                                         if (lpParms->dwTrack > AnimDev[wDevID].nTracks)
314                                                 return MCIERR_OUTOFRANGE;
315                                         lpParms->dwReturn = AnimDev[wDevID].lpdwTrackLen[lpParms->dwTrack];
316                                         }
317                                 else
318                                         lpParms->dwReturn = AnimDev[wDevID].dwTotalLen;
319                                 lpParms->dwReturn = ANIM_CalcTime(wDevID, 
320                                         AnimDev[wDevID].dwTimeFormat, lpParms->dwReturn);
321                                 TRACE(mcianim,"LENGTH=%lu !\n", lpParms->dwReturn);
322                                 return 0;
323                         case MCI_STATUS_MODE:
324                                 lpParms->dwReturn = AnimDev[wDevID].mode;
325                                 TRACE(mcianim,"MCI_STATUS_MODE=%08lX !\n",
326                                                                                                 lpParms->dwReturn);
327                                 return 0;
328                         case MCI_STATUS_MEDIA_PRESENT:
329                                 lpParms->dwReturn = TRUE;
330                                 TRACE(mcianim,"MCI_STATUS_MEDIA_PRESENT !\n");
331                                 return 0;
332                         case MCI_STATUS_NUMBER_OF_TRACKS:
333                                 lpParms->dwReturn = 1;
334                                 TRACE(mcianim,"MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n",
335                                                                                         lpParms->dwReturn);
336                                 if (lpParms->dwReturn == (WORD)-1) return MCIERR_INTERNAL;
337                                 return 0;
338                         case MCI_STATUS_POSITION:
339                                 lpParms->dwReturn = AnimDev[wDevID].dwCurFrame;
340                                 if (dwFlags & MCI_STATUS_START) {
341                                         lpParms->dwReturn = 0;
342                                         TRACE(mcianim,"get MCI_STATUS_START !\n");
343                                         }
344                                 if (dwFlags & MCI_TRACK) {
345                                         if (lpParms->dwTrack > AnimDev[wDevID].nTracks)
346                                                 return MCIERR_OUTOFRANGE;
347                                         lpParms->dwReturn = AnimDev[wDevID].lpdwTrackPos[lpParms->dwTrack - 1];
348                                         TRACE(mcianim,"get MCI_TRACK #%lu !\n", lpParms->dwTrack);
349                                         }
350                                 lpParms->dwReturn = ANIM_CalcTime(wDevID, 
351                                         AnimDev[wDevID].dwTimeFormat, lpParms->dwReturn);
352                                         TRACE(mcianim,"MCI_STATUS_POSITION=%08lX !\n",
353                                                                                                                 lpParms->dwReturn);
354                                 return 0;
355                         case MCI_STATUS_READY:
356                                 TRACE(mcianim,"MCI_STATUS_READY !\n");
357                                 lpParms->dwReturn = TRUE;
358                                 return 0;
359                         case MCI_STATUS_TIME_FORMAT:
360                                 TRACE(mcianim,"MCI_STATUS_TIME_FORMAT !\n");
361                                 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
362                                 return 0;
363                         default:
364                                 WARN(mcianim,"Unknown command %08lX !\n", lpParms->dwItem);
365                                 return MCIERR_UNRECOGNIZED_COMMAND;
366                         }
367                 }
368     WARN(mcianim,"Not MCI_STATUS_ITEM !\n");
369         return 0;
370 }
371
372
373 /**************************************************************************
374 *                               ANIM_mciPlay                    [internal]
375 */
376 static DWORD ANIM_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
377 {
378         int     start, end;
379         TRACE(mcianim,"(%u, %08lX, %p);\n", 
380                 wDevID, dwFlags, lpParms);
381         if (lpParms == NULL) return MCIERR_INTERNAL;
382         start = 0;              end = AnimDev[wDevID].dwTotalLen;
383         AnimDev[wDevID].nCurTrack = 1;
384         if (dwFlags & MCI_FROM) {
385                 start = ANIM_CalcFrame(wDevID, 
386                         AnimDev[wDevID].dwTimeFormat, lpParms->dwFrom); 
387         TRACE(mcianim,"MCI_FROM=%08lX -> %u \n",
388                                 lpParms->dwFrom, start);
389                 }
390         if (dwFlags & MCI_TO) {
391                 end = ANIM_CalcFrame(wDevID, 
392                         AnimDev[wDevID].dwTimeFormat, lpParms->dwTo);
393                 TRACE(mcianim, "MCI_TO=%08lX -> %u \n",
394                         lpParms->dwTo, end);
395                 }
396         AnimDev[wDevID].mode = MCI_MODE_PLAY;
397         if (dwFlags & MCI_NOTIFY) {
398                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
399                         lpParms->dwCallback);
400                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
401                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
402                 }
403         return 0;
404 }
405
406 /**************************************************************************
407 *                               ANIM_mciStop                    [internal]
408 */
409 static DWORD ANIM_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
410 {
411         TRACE(mcianim,"(%u, %08lX, %p);\n", 
412                         wDevID, dwFlags, lpParms);
413         if (lpParms == NULL) return MCIERR_INTERNAL;
414         AnimDev[wDevID].mode = MCI_MODE_STOP;
415         if (dwFlags & MCI_NOTIFY) {
416                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
417                         lpParms->dwCallback);
418                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
419                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
420                 }
421         return 0;
422 }
423
424 /**************************************************************************
425 *                               ANIM_mciPause           [internal]
426 */
427 static DWORD ANIM_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
428 {
429         TRACE(mcianim,"(%u, %08lX, %p);\n", 
430                 wDevID, dwFlags, lpParms);
431         if (lpParms == NULL) return MCIERR_INTERNAL;
432         AnimDev[wDevID].mode = MCI_MODE_PAUSE;
433         if (dwFlags & MCI_NOTIFY) {
434                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
435                         lpParms->dwCallback);
436                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
437                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
438                 }
439         return 0;
440 }
441
442 /**************************************************************************
443 *                               ANIM_mciResume          [internal]
444 */
445 static DWORD ANIM_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
446 {
447         TRACE(mcianim,"(%u, %08lX, %p);\n", 
448                 wDevID, dwFlags, lpParms);
449         if (lpParms == NULL) return MCIERR_INTERNAL;
450         AnimDev[wDevID].mode = MCI_MODE_STOP;
451         if (dwFlags & MCI_NOTIFY) {
452                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
453                         lpParms->dwCallback);
454                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
455                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
456                 }
457         return 0;
458 }
459
460 /**************************************************************************
461 *                               ANIM_mciSeek                    [internal]
462 */
463 static DWORD ANIM_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
464 {
465         DWORD   dwRet;
466         MCI_PLAY_PARMS PlayParms;
467         TRACE(mcianim,"(%u, %08lX, %p);\n", 
468                 wDevID, dwFlags, lpParms);
469         if (lpParms == NULL) return MCIERR_INTERNAL;
470         AnimDev[wDevID].mode = MCI_MODE_SEEK;
471         switch(dwFlags) {
472                 case MCI_SEEK_TO_START:
473                         PlayParms.dwFrom = 0;
474                         break;
475                 case MCI_SEEK_TO_END:
476                         PlayParms.dwFrom = AnimDev[wDevID].dwTotalLen;
477                         break;
478                 case MCI_TO:
479                         PlayParms.dwFrom = lpParms->dwTo;
480                         break;
481                 }
482         dwRet = ANIM_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms);
483         if (dwRet != 0) return dwRet;
484         dwRet = ANIM_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms);
485         if (dwFlags & MCI_NOTIFY) {
486                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
487                         lpParms->dwCallback);
488                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
489                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
490                 }
491         return dwRet;
492 }
493
494
495 /**************************************************************************
496 *                               ANIM_mciSet                     [internal]
497 */
498 static DWORD ANIM_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
499 {
500         TRACE(mcianim,"(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
501         if (lpParms == NULL) return MCIERR_INTERNAL;
502 /*
503         TRACE(mcianim,"(dwTimeFormat=%08lX)\n", lpParms->dwTimeFormat);
504         TRACE(mcianim,"(dwAudio=%08lX)\n", lpParms->dwAudio);
505 */
506         if (dwFlags & MCI_SET_TIME_FORMAT) {
507                 switch (lpParms->dwTimeFormat) {
508                         case MCI_FORMAT_MILLISECONDS:
509                                 TRACE(mcianim, "MCI_FORMAT_MILLISECONDS !\n");
510                                 break;
511                         case MCI_FORMAT_MSF:
512                                 TRACE(mcianim,"MCI_FORMAT_MSF !\n");
513                                 break;
514                         case MCI_FORMAT_TMSF:
515                                 TRACE(mcianim,"MCI_FORMAT_TMSF !\n");
516                                 break;
517                         default:
518                                 WARN(mcianim,"Bad time format !\n");
519                                 return MCIERR_BAD_TIME_FORMAT;
520                         }
521                 AnimDev[wDevID].dwTimeFormat = lpParms->dwTimeFormat;
522                 }
523         if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
524         if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
525         if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
526         if (dwFlags & MCI_NOTIFY) {
527                 TRACE(mcianim, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
528                         lpParms->dwCallback);
529                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
530                         AnimDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
531                 }
532         return 0;
533 }
534
535
536 /**************************************************************************
537 *                               ANIM_DriverProc         [sample driver]
538 */
539 LONG ANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
540                      DWORD dwParam1, DWORD dwParam2)
541 {
542         switch(wMsg) {
543                 case DRV_LOAD:
544                         return 1;
545                 case DRV_FREE:
546                         return 1;
547                 case DRV_OPEN:
548                 case MCI_OPEN_DRIVER:
549                 case MCI_OPEN:
550                         return ANIM_mciOpen(dwDevID, dwParam1, 
551                                         (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2)); 
552                 case DRV_CLOSE:
553                 case MCI_CLOSE_DRIVER:
554                 case MCI_CLOSE:
555                         return ANIM_mciClose(dwDevID, dwParam1, 
556                                         (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
557                 case DRV_ENABLE:
558                         return 1;
559                 case DRV_DISABLE:
560                         return 1;
561                 case DRV_QUERYCONFIGURE:
562                         return 1;
563                 case DRV_CONFIGURE:
564                         MessageBox16(0, "Sample MultiMedia Linux Driver !", 
565                                                                 "MMLinux Driver", MB_OK);
566                         return 1;
567                 case DRV_INSTALL:
568                         return DRVCNF_RESTART;
569                 case DRV_REMOVE:
570                         return DRVCNF_RESTART;
571                 case MCI_GETDEVCAPS:
572                         return ANIM_mciGetDevCaps(dwDevID, dwParam1, 
573                                         (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
574                 case MCI_INFO:
575                         return ANIM_mciInfo(dwDevID, dwParam1, 
576                                                 (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
577                 case MCI_STATUS:
578                         return ANIM_mciStatus(dwDevID, dwParam1, 
579                                                 (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
580                 case MCI_SET:
581                         return ANIM_mciSet(dwDevID, dwParam1, 
582                                                 (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
583                 case MCI_PLAY:
584                         return ANIM_mciPlay(dwDevID, dwParam1, 
585                                                 (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
586                 case MCI_STOP:
587                         return ANIM_mciStop(dwDevID, dwParam1, 
588                                         (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
589                 case MCI_PAUSE:
590                         return ANIM_mciPause(dwDevID, dwParam1, 
591                                         (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
592                 case MCI_RESUME:
593                         return ANIM_mciResume(dwDevID, dwParam1, 
594                                         (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
595                 case MCI_SEEK:
596                         return ANIM_mciSeek(dwDevID, dwParam1, 
597                                         (LPMCI_SEEK_PARMS)PTR_SEG_TO_LIN(dwParam2));
598                 default:
599                         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
600                 }
601 }
602
603
604 /*-----------------------------------------------------------------------*/