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