Added mappings for a few messages.
[wine] / dlls / winmm / mcianim / mcianim.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3  * Sample MCI ANIMATION Wine Driver for Linux
4  *
5  * Copyright 1994 Martin Ayotte
6  */
7
8 #include <string.h>
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "mmddk.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(mcianim);
17
18 #define ANIMFRAMES_PERSEC       30
19 #define ANIMFRAMES_PERMIN       1800
20 #define SECONDS_PERMIN          60
21
22 typedef struct {
23         UINT16          wDevID;
24         int             nUseCount;          /* Incremented for each shared open */
25         BOOL16          fShareable;         /* TRUE if first open was shareable */
26         WORD            wNotifyDeviceID;    /* MCI device ID with a pending notification */
27         HANDLE16        hCallback;          /* Callback handle for pending notification */
28         MCI_OPEN_PARMSA openParms;
29         DWORD           dwTimeFormat;
30         int             mode;
31         UINT16          nCurTrack;
32         DWORD           dwCurFrame;
33         UINT16          nTracks;
34         DWORD           dwTotalLen;
35         LPDWORD         lpdwTrackLen;
36         LPDWORD         lpdwTrackPos;
37 } WINE_MCIANIM;
38
39 /*-----------------------------------------------------------------------*/
40
41 /**************************************************************************
42  *                              MCIANIM_drvOpen                 [internal]      
43  */
44 static  DWORD   MCIANIM_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
45 {
46     WINE_MCIANIM*       wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIANIM));
47
48     if (!wma)
49         return 0;
50
51     wma->wDevID = modp->wDeviceID;
52     mciSetDriverData(wma->wDevID, (DWORD)wma);
53     modp->wCustomCommandTable = MCI_NO_COMMAND_TABLE;
54     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
55     return modp->wDeviceID;
56 }
57
58 /**************************************************************************
59  *                              MCIANIM_drvClose                [internal]      
60  */
61 static  DWORD   MCIANIM_drvClose(DWORD dwDevID)
62 {
63     WINE_MCIANIM*  wma = (WINE_MCIANIM*)mciGetDriverData(dwDevID);
64
65     if (wma) {
66         HeapFree(GetProcessHeap(), 0, wma);
67         return 1;
68     }
69     return 0;
70 }
71
72 /**************************************************************************
73  *                              MCIANIM_mciGetOpenDrv           [internal]      
74  */
75 static WINE_MCIANIM*  MCIANIM_mciGetOpenDrv(UINT16 wDevID)
76 {
77     WINE_MCIANIM*       wma = (WINE_MCIANIM*)mciGetDriverData(wDevID);
78     
79     if (wma == NULL || wma->nUseCount == 0) {
80         WARN("Invalid wDevID=%u\n", wDevID);
81         return 0;
82     }
83     return wma;
84 }
85
86 /**************************************************************************
87  *                              MCIANIM_mciOpen                 [internal]
88  */
89 static DWORD MCIANIM_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
90 {
91     DWORD               dwDeviceID;
92     WINE_MCIANIM*       wma = (WINE_MCIANIM*)mciGetDriverData(wDevID);
93     
94     TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
95     
96     if (lpOpenParms == NULL)    return MCIERR_INTERNAL;
97     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
98     
99     if (wma->nUseCount > 0) {
100         /* The driver already open on this channel */
101         /* If the driver was opened shareable before and this open specifies */
102         /* shareable then increment the use count */
103         if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
104             ++wma->nUseCount;
105         else
106             return MCIERR_MUST_USE_SHAREABLE;
107     } else {
108         wma->nUseCount = 1;
109         wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
110     }
111     
112     dwDeviceID = lpOpenParms->wDeviceID;
113     
114     TRACE("wDevID=%04X\n", wDevID);
115     /* FIXME this is not consistent with other implementations */
116     lpOpenParms->wDeviceID = wDevID;
117     
118     /*TRACE("lpParms->wDevID=%04X\n", lpParms->wDeviceID);*/
119     if (dwFlags & MCI_OPEN_ELEMENT) {
120         TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms->lpstrElementName);
121         if (lpOpenParms->lpstrElementName && strlen(lpOpenParms->lpstrElementName) > 0) {
122         }
123         FIXME("element is not opened\n");
124     }
125     memcpy(&wma->openParms, lpOpenParms, sizeof(MCI_OPEN_PARMSA));
126     wma->wNotifyDeviceID = dwDeviceID;
127     wma->mode = 0;
128     wma->dwTimeFormat = MCI_FORMAT_TMSF;
129     wma->nCurTrack = 0;
130     wma->nTracks = 0;
131     wma->dwTotalLen = 0;
132     wma->lpdwTrackLen = NULL;
133     wma->lpdwTrackPos = NULL;
134     /*
135       Moved to mmsystem.c mciOpen routine 
136       
137       if (dwFlags & MCI_NOTIFY) {
138       TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
139       lpParms->dwCallback);
140       mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
141       wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
142       }
143     */
144     return 0;
145 }
146
147 /**************************************************************************
148  *                              MCIANIM_mciClose                [internal]
149  */
150 static DWORD MCIANIM_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
151 {
152     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
153     
154     TRACE("(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
155     
156     if (wma == NULL)     return MCIERR_INVALID_DEVICE_ID;
157     
158     if (--wma->nUseCount == 0) {
159         /* do the actual clean-up */
160     }
161     return 0;
162 }
163
164 /**************************************************************************
165  *                              MCIANIM_mciGetDevCaps   [internal]
166  */
167 static DWORD MCIANIM_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags, 
168                                 LPMCI_GETDEVCAPS_PARMS lpParms)
169 {
170     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
171     DWORD               ret;
172
173     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
174     
175     if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
176     if (wma == NULL)     return MCIERR_INVALID_DEVICE_ID;
177     
178     if (dwFlags & MCI_GETDEVCAPS_ITEM) {
179         TRACE("MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms->dwItem);
180
181         switch(lpParms->dwItem) {
182         case MCI_GETDEVCAPS_CAN_RECORD:
183             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
184             ret = MCI_RESOURCE_RETURNED;
185             break;
186         case MCI_GETDEVCAPS_HAS_AUDIO:
187             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
188             ret = MCI_RESOURCE_RETURNED;
189             break;
190         case MCI_GETDEVCAPS_HAS_VIDEO:
191             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
192             ret = MCI_RESOURCE_RETURNED;
193             break;
194         case MCI_GETDEVCAPS_DEVICE_TYPE:
195             lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_ANIMATION, MCI_DEVTYPE_ANIMATION);
196             ret = MCI_RESOURCE_RETURNED;
197             break;
198         case MCI_GETDEVCAPS_USES_FILES:
199             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
200             ret = MCI_RESOURCE_RETURNED;
201             break;
202         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
203             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
204             ret = MCI_RESOURCE_RETURNED;
205             break;
206         case MCI_GETDEVCAPS_CAN_EJECT:
207             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
208             ret = MCI_RESOURCE_RETURNED;
209             break;
210         case MCI_GETDEVCAPS_CAN_PLAY:
211             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
212             ret = MCI_RESOURCE_RETURNED;
213             break;
214         case MCI_GETDEVCAPS_CAN_SAVE:
215             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
216             ret = MCI_RESOURCE_RETURNED;
217             break;
218         default:
219             FIXME("Unknown capability (%08lx) !\n", lpParms->dwItem);
220             return MCIERR_UNRECOGNIZED_COMMAND;
221         }
222     } else {
223         WARN("No GETDEVCAPS_ITEM !\n");
224         return MCIERR_UNRECOGNIZED_COMMAND;
225     }
226     TRACE("lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
227     return ret;
228 }
229
230
231 /**************************************************************************
232  *                              MCIANIM_CalcTime                        [internal]
233  */
234 static DWORD MCIANIM_CalcTime(WINE_MCIANIM* wma, DWORD dwFormatType, DWORD dwFrame, LPDWORD lpRet)
235 {
236     DWORD       dwTime = 0;
237     UINT16      wTrack;
238     UINT16      wMinutes;
239     UINT16      wSeconds;
240     UINT16      wFrames;
241     
242     TRACE("(%p, %08lX, %lu);\n", wma, dwFormatType, dwFrame);
243     
244     switch (dwFormatType) {
245     case MCI_FORMAT_MILLISECONDS:
246         dwTime = dwFrame / ANIMFRAMES_PERSEC * 1000;
247         *lpRet = 0;
248         TRACE("MILLISECONDS %lu\n", dwTime);
249         break;
250     case MCI_FORMAT_MSF:
251         wMinutes = dwFrame / ANIMFRAMES_PERMIN;
252         wSeconds = (dwFrame - ANIMFRAMES_PERMIN * wMinutes) / ANIMFRAMES_PERSEC;
253         wFrames = dwFrame - ANIMFRAMES_PERMIN * wMinutes - 
254             ANIMFRAMES_PERSEC * wSeconds;
255         dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
256         TRACE("MSF %02u:%02u:%02u -> dwTime=%lu\n",wMinutes, wSeconds, wFrames, dwTime);
257         *lpRet = MCI_COLONIZED3_RETURN;
258         break;
259     default:
260         /* unknown format ! force TMSF ! ... */
261         dwFormatType = MCI_FORMAT_TMSF;
262     case MCI_FORMAT_TMSF:
263         for (wTrack = 0; wTrack < wma->nTracks; wTrack++) {
264             /*                          dwTime += wma->lpdwTrackLen[wTrack - 1];
265                                         TRACE("Adding trk#%u curpos=%u \n", dwTime);
266                                         if (dwTime >= dwFrame) break; */
267             if (wma->lpdwTrackPos[wTrack - 1] >= dwFrame) break;
268         }
269         wMinutes = dwFrame / ANIMFRAMES_PERMIN;
270         wSeconds = (dwFrame - ANIMFRAMES_PERMIN * wMinutes) / ANIMFRAMES_PERSEC;
271         wFrames = dwFrame - ANIMFRAMES_PERMIN * wMinutes - 
272             ANIMFRAMES_PERSEC * wSeconds;
273         dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
274         *lpRet = MCI_COLONIZED4_RETURN;
275         TRACE("%02u-%02u:%02u:%02u\n", wTrack, wMinutes, wSeconds, wFrames);
276         break;
277     }
278     return dwTime;
279 }
280
281
282 /**************************************************************************
283  *                              MCIANIM_CalcFrame                       [internal]
284  */
285 static DWORD MCIANIM_CalcFrame(WINE_MCIANIM* wma, DWORD dwFormatType, DWORD dwTime)
286 {
287     DWORD       dwFrame = 0;
288     UINT16      wTrack;
289     
290     TRACE("(%p, %08lX, %lu);\n", wma, dwFormatType, dwTime);
291     
292     switch (dwFormatType) {
293     case MCI_FORMAT_MILLISECONDS:
294         dwFrame = dwTime * ANIMFRAMES_PERSEC / 1000;
295         TRACE("MILLISECONDS %lu\n", dwFrame);
296         break;
297     case MCI_FORMAT_MSF:
298         TRACE("MSF %02u:%02u:%02u\n",
299               MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), 
300               MCI_MSF_FRAME(dwTime));
301         dwFrame += ANIMFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
302         dwFrame += ANIMFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
303         dwFrame += MCI_MSF_FRAME(dwTime);
304         break;
305     default:
306         /* unknown format ! force TMSF ! ... */
307         dwFormatType = MCI_FORMAT_TMSF;
308     case MCI_FORMAT_TMSF:
309         wTrack = MCI_TMSF_TRACK(dwTime);
310         TRACE("TMSF %02u-%02u:%02u:%02u\n",
311               MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), 
312               MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
313         TRACE("TMSF trackpos[%u]=%lu\n",
314               wTrack, wma->lpdwTrackPos[wTrack - 1]);
315         dwFrame = wma->lpdwTrackPos[wTrack - 1];
316         dwFrame += ANIMFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
317         dwFrame += ANIMFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
318         dwFrame += MCI_TMSF_FRAME(dwTime);
319         break;
320     }
321     return dwFrame;
322 }
323
324 /**************************************************************************
325  *                              MCIANIM_mciInfo                 [internal]
326  */
327 static DWORD MCIANIM_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
328 {
329     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
330     LPSTR               str = 0;
331     DWORD               ret = 0;
332     
333     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
334     
335     if (lpParms == NULL || lpParms->lpstrReturn == NULL)
336         return MCIERR_NULL_PARAMETER_BLOCK;
337
338     if (wma == NULL)
339         return MCIERR_INVALID_DEVICE_ID;
340     
341     TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
342     
343     switch(dwFlags) {
344     case MCI_INFO_PRODUCT:
345         str = "Wine's animation";
346         break;
347     case MCI_INFO_FILE:
348         str = wma->openParms.lpstrElementName;
349         break;
350     case MCI_ANIM_INFO_TEXT:
351         str = "Animation Window";
352         break;
353     default:
354         WARN("Don't know this info command (%lu)\n", dwFlags);
355         return MCIERR_UNRECOGNIZED_COMMAND;
356     }
357
358     if (str) {
359         if (lpParms->dwRetSize <= strlen(str)) {
360             lstrcpynA(lpParms->lpstrReturn, str, lpParms->dwRetSize - 1);
361             ret = MCIERR_PARAM_OVERFLOW;
362         } else {
363             strcpy(lpParms->lpstrReturn, str);
364         }       
365     } else {
366         *lpParms->lpstrReturn = 0;
367     }
368     return ret;
369 }
370
371 /**************************************************************************
372  *                              MCIANIM_mciStatus               [internal]
373  */
374 static DWORD MCIANIM_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
375 {
376     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
377     DWORD               ret;
378
379     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
380     
381     if (lpParms == NULL) return MCIERR_INTERNAL;
382     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
383     
384     if (dwFlags & MCI_NOTIFY) {
385         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
386
387         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
388                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
389     }
390     if (dwFlags & MCI_STATUS_ITEM) {
391         switch(lpParms->dwItem) {
392         case MCI_STATUS_CURRENT_TRACK:
393             lpParms->dwReturn = wma->nCurTrack;
394             TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
395             break;
396         case MCI_STATUS_LENGTH:
397             if (dwFlags & MCI_TRACK) {
398                 TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
399                 if (lpParms->dwTrack > wma->nTracks)
400                     return MCIERR_OUTOFRANGE;
401                 lpParms->dwReturn = wma->lpdwTrackLen[lpParms->dwTrack];
402             }
403             else
404                 lpParms->dwReturn = wma->dwTotalLen;
405             lpParms->dwReturn = MCIANIM_CalcTime(wma, wma->dwTimeFormat, lpParms->dwReturn, &ret);
406             TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
407             break;
408         case MCI_STATUS_MODE:
409             TRACE("MCI_STATUS_MODE=%04X !\n", wma->mode);
410             lpParms->dwReturn = MAKEMCIRESOURCE(wma->mode, wma->mode);
411             ret = MCI_RESOURCE_RETURNED;
412             break;
413         case MCI_STATUS_MEDIA_PRESENT:
414             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
415             ret = MCI_RESOURCE_RETURNED;
416             TRACE("MCI_STATUS_MEDIA_PRESENT !\n");
417             break;
418         case MCI_STATUS_NUMBER_OF_TRACKS:
419             lpParms->dwReturn = 1;
420             TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
421             break;
422         case MCI_STATUS_POSITION:
423             lpParms->dwReturn = wma->dwCurFrame;
424             if (dwFlags & MCI_STATUS_START) {
425                 lpParms->dwReturn = 0;
426                 TRACE("get MCI_STATUS_START !\n");
427             }
428             if (dwFlags & MCI_TRACK) {
429                 if (lpParms->dwTrack > wma->nTracks)
430                     return MCIERR_OUTOFRANGE;
431                 lpParms->dwReturn = wma->lpdwTrackPos[lpParms->dwTrack - 1];
432                 TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
433             }
434             lpParms->dwReturn = MCIANIM_CalcTime(wma, wma->dwTimeFormat, lpParms->dwReturn, &ret);
435             TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
436             break;
437         case MCI_STATUS_READY:
438             TRACE("MCI_STATUS_READY !\n");
439             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
440             ret = MCI_RESOURCE_RETURNED;
441             return 0;
442         case MCI_STATUS_TIME_FORMAT:
443             TRACE("MCI_STATUS_TIME_FORMAT !\n");
444             lpParms->dwReturn = MAKEMCIRESOURCE(MCI_FORMAT_MILLISECONDS, MCI_FORMAT_MILLISECONDS);
445             TRACE("MCI_STATUS_TIME_FORMAT => %u\n", LOWORD(lpParms->dwReturn));
446             ret = MCI_RESOURCE_RETURNED;
447             return 0;
448         default:
449             FIXME("Unknown command %08lX !\n", lpParms->dwItem);
450             return MCIERR_UNRECOGNIZED_COMMAND;
451         }
452     } else {
453         WARN("No MCI_STATUS_ITEM !\n");
454         return MCIERR_UNRECOGNIZED_COMMAND;
455     }
456     return ret;
457 }
458
459
460 /**************************************************************************
461  *                              MCIANIM_mciPlay                 [internal]
462  */
463 static DWORD MCIANIM_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
464 {
465     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
466     int         start, end;
467     
468     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
469     
470     if (lpParms == NULL) return MCIERR_INTERNAL;
471     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
472     
473     start = 0;          end = wma->dwTotalLen;
474     wma->nCurTrack = 1;
475     if (dwFlags & MCI_FROM) {
476         start = MCIANIM_CalcFrame(wma, wma->dwTimeFormat, lpParms->dwFrom); 
477         TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
478     }
479     if (dwFlags & MCI_TO) {
480         end = MCIANIM_CalcFrame(wma, wma->dwTimeFormat, lpParms->dwTo);
481         TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
482     }
483     wma->mode = MCI_MODE_PLAY;
484     if (dwFlags & MCI_NOTIFY) {
485         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
486               lpParms->dwCallback);
487         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
488                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
489     }
490     return 0;
491 }
492
493 /**************************************************************************
494  *                              MCIANIM_mciStop                 [internal]
495  */
496 static DWORD MCIANIM_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
497 {
498     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
499     
500     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
501     
502     if (lpParms == NULL) return MCIERR_INTERNAL;
503     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
504     
505     wma->mode = MCI_MODE_STOP;
506     if (dwFlags & MCI_NOTIFY) {
507         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
508
509         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
510                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
511     }
512     return 0;
513 }
514
515 /**************************************************************************
516  *                              MCIANIM_mciPause                [internal]
517  */
518 static DWORD MCIANIM_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
519 {
520     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
521     
522     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
523     if (lpParms == NULL) return MCIERR_INTERNAL;
524     wma->mode = MCI_MODE_PAUSE;
525     if (dwFlags & MCI_NOTIFY) {
526         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
527
528         mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
529                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
530     }
531     return 0;
532 }
533
534 /**************************************************************************
535  *                              MCIANIM_mciResume               [internal]
536  */
537 static DWORD MCIANIM_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
538 {
539     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
540     
541     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
542     if (lpParms == NULL) return MCIERR_INTERNAL;
543     wma->mode = MCI_MODE_STOP;
544     if (dwFlags & MCI_NOTIFY) {
545         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
546
547         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
548                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
549     }
550     return 0;
551 }
552
553 /**************************************************************************
554  *                              MCIANIM_mciSeek                 [internal]
555  */
556 static DWORD MCIANIM_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
557 {
558     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
559     DWORD       dwRet;
560     MCI_PLAY_PARMS PlayParms;
561     
562     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
563     
564     if (lpParms == NULL) return MCIERR_INTERNAL;
565     wma->mode = MCI_MODE_SEEK;
566     switch (dwFlags) {
567     case MCI_SEEK_TO_START:
568         PlayParms.dwFrom = 0;
569         break;
570     case MCI_SEEK_TO_END:
571         PlayParms.dwFrom = wma->dwTotalLen;
572         break;
573     case MCI_TO:
574         PlayParms.dwFrom = lpParms->dwTo;
575         break;
576     }
577     dwRet = MCIANIM_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms);
578     if (dwRet != 0) return dwRet;
579     dwRet = MCIANIM_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms);
580     if (dwFlags & MCI_NOTIFY) {
581         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
582
583         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
584                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
585     }
586     return dwRet;
587 }
588
589
590 /**************************************************************************
591  *                              MCIANIM_mciSet                  [internal]
592  */
593 static DWORD MCIANIM_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
594 {
595     WINE_MCIANIM*       wma = MCIANIM_mciGetOpenDrv(wDevID);
596     
597     TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
598
599     if (lpParms == NULL) return MCIERR_INTERNAL;
600     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
601     /*
602       TRACE("(dwTimeFormat=%08lX)\n", lpParms->dwTimeFormat);
603       TRACE("(dwAudio=%08lX)\n", lpParms->dwAudio);
604     */
605     if (dwFlags & MCI_SET_TIME_FORMAT) {
606         switch (lpParms->dwTimeFormat) {
607         case MCI_FORMAT_MILLISECONDS:
608             TRACE("MCI_FORMAT_MILLISECONDS !\n");
609             break;
610         case MCI_FORMAT_MSF:
611             TRACE("MCI_FORMAT_MSF !\n");
612             break;
613         case MCI_FORMAT_TMSF:
614             TRACE("MCI_FORMAT_TMSF !\n");
615             break;
616         default:
617             WARN("Bad time format !\n");
618             return MCIERR_BAD_TIME_FORMAT;
619         }
620         wma->dwTimeFormat = lpParms->dwTimeFormat;
621     }
622     if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
623     if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
624     if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
625     if (dwFlags & MCI_NOTIFY) {
626         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
627         mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
628                           wma->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
629     }
630     return 0;
631 }
632
633 /**************************************************************************
634  *                              DriverProc (MCIANIM.@)
635  */
636 LONG WINAPI MCIANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
637                                DWORD dwParam1, DWORD dwParam2)
638 {
639     switch (wMsg) {
640     case DRV_LOAD:              return 1;
641     case DRV_FREE:              return 1; 
642     case DRV_OPEN:              return MCIANIM_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
643     case DRV_CLOSE:             return MCIANIM_drvClose(dwDevID);
644     case DRV_ENABLE:            return 1;
645     case DRV_DISABLE:           return 1;
646     case DRV_QUERYCONFIGURE:    return 1;
647     case DRV_CONFIGURE:         MessageBoxA(0, "Sample MultiMedia Driver !", "Wine Driver", MB_OK); return 1;
648     case DRV_INSTALL:           return DRVCNF_RESTART;
649     case DRV_REMOVE:            return DRVCNF_RESTART;
650         
651     case MCI_OPEN_DRIVER:       return MCIANIM_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2); 
652     case MCI_CLOSE_DRIVER:      return MCIANIM_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
653     case MCI_GETDEVCAPS:        return MCIANIM_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
654     case MCI_INFO:              return MCIANIM_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
655     case MCI_STATUS:            return MCIANIM_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
656     case MCI_SET:               return MCIANIM_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
657     case MCI_PLAY:              return MCIANIM_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
658     case MCI_STOP:              return MCIANIM_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
659     case MCI_PAUSE:             return MCIANIM_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
660     case MCI_RESUME:            return MCIANIM_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
661     case MCI_SEEK:              return MCIANIM_mciSeek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
662     case MCI_LOAD:              
663     case MCI_SAVE:              
664     case MCI_FREEZE:            
665     case MCI_PUT:               
666     case MCI_REALIZE:           
667     case MCI_UNFREEZE:          
668     case MCI_UPDATE:            
669     case MCI_WHERE:             
670     case MCI_WINDOW:            
671     case MCI_STEP:              
672     case MCI_SPIN:              
673     case MCI_ESCAPE:            
674     case MCI_COPY:              
675     case MCI_CUT:               
676     case MCI_DELETE:            
677     case MCI_PASTE:             
678         FIXME("Unsupported message [%lu]\n", wMsg);
679         break;
680     case MCI_OPEN:
681     case MCI_CLOSE:
682         ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
683         break;
684     default:                    
685         TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
686         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
687     }
688     return MCIERR_UNRECOGNIZED_COMMAND;
689 }
690
691 /*-----------------------------------------------------------------------*/