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