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