Fixed traces.
[wine] / dlls / winmm / mciavi / mciavi.c
1
2
3 /*
4  * Digital video MCI Wine Driver
5  *
6  * Copyright 1999, 2000 Eric POUECH
7  * Copyright 2003 Dmitry Timoshkov
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 /* TODO list :
25  *      - handling of palettes
26  *      - recording (which input devices ?), a cam recorder ?
27  *      - lots of messages still need to be handled (cf FIXME)
28  *      - synchronization between audio and video (especially for interleaved
29  *        files)
30  *      - robustness when reading file can be enhanced
31  *      - better move the AVI handling part to avifile DLL and make use of it
32  *      - some files appear to have more than one audio stream (we only play the
33  *        first one)
34  *      - some files contain an index of audio/video frame. Better use it,
35  *        instead of rebuilding it
36  *      - stopping while playing a file with sound blocks until all buffered
37  *        audio is played... still should be stopped ASAP
38  */
39
40 #include <string.h>
41 #include "private_mciavi.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
44
45 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
46
47 static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
48
49 /* ===================================================================
50  * ===================================================================
51  * FIXME: should be using the new mmThreadXXXX functions from WINMM
52  * instead of those
53  * it would require to add a wine internal flag to mmThreadCreate
54  * in order to pass a 32 bit function instead of a 16 bit one
55  * ===================================================================
56  * =================================================================== */
57
58 struct SCA {
59     MCIDEVICEID wDevID;
60     UINT        wMsg;
61     DWORD_PTR   dwParam1;
62     DWORD_PTR   dwParam2;
63 };
64
65 /**************************************************************************
66  *                              MCI_SCAStarter                  [internal]
67  */
68 static DWORD CALLBACK   MCI_SCAStarter(LPVOID arg)
69 {
70     struct SCA* sca = (struct SCA*)arg;
71     DWORD       ret;
72
73     TRACE("In thread before async command (%08x,%04x,%08lx,%08lx)\n",
74           sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
75     ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
76     TRACE("In thread after async command (%08x,%04x,%08lx,%08lx)\n",
77           sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
78     HeapFree(GetProcessHeap(), 0, sca);
79     return ret;
80 }
81
82 /**************************************************************************
83  *                              MCI_SendCommandAsync            [internal]
84  */
85 static  DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,
86                                   DWORD_PTR dwParam2, UINT size)
87 {
88     HANDLE handle;
89     struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
90
91     if (sca == 0)
92         return MCIERR_OUT_OF_MEMORY;
93
94     sca->wDevID   = wDevID;
95     sca->wMsg     = wMsg;
96     sca->dwParam1 = dwParam1;
97
98     if (size && dwParam2) {
99        sca->dwParam2 = (DWORD_PTR)sca + sizeof(struct SCA);
100         /* copy structure passed by program in dwParam2 to be sure
101          * we can still use it whatever the program does
102          */
103         memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
104     } else {
105         sca->dwParam2 = dwParam2;
106     }
107
108     if ((handle = CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL)) == 0) {
109         WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
110         return MCI_SCAStarter(&sca);
111     }
112     SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
113     CloseHandle(handle);
114     return 0;
115 }
116
117 /*======================================================================*
118  *                          MCI AVI implemantation                      *
119  *======================================================================*/
120
121 HINSTANCE MCIAVI_hInstance = 0;
122
123 /***********************************************************************
124  *              DllMain (MCIAVI.0)
125  */
126 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
127 {
128     switch (fdwReason) {
129     case DLL_PROCESS_ATTACH:
130         DisableThreadLibraryCalls(hInstDLL);
131         MCIAVI_hInstance = hInstDLL;
132         break;
133     }
134     return TRUE;
135 }
136
137 /**************************************************************************
138  *                              MCIAVI_drvOpen                  [internal]
139  */
140 static  DWORD   MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
141 {
142     WINE_MCIAVI*        wma;
143     static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
144
145     TRACE("%s, %p\n", debugstr_w(str), modp);
146
147     /* session instance */
148     if (!modp) return 0xFFFFFFFF;
149
150     if (!MCIAVI_RegisterClass()) return 0;
151
152     wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
153     if (!wma)
154         return 0;
155
156     InitializeCriticalSection(&wma->cs);
157     wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
158     wma->wDevID = modp->wDeviceID;
159     wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
160     modp->wCustomCommandTable = wma->wCommandTable;
161     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
162     mciSetDriverData(wma->wDevID, (DWORD)wma);
163
164     return modp->wDeviceID;
165 }
166
167 /**************************************************************************
168  *                              MCIAVI_drvClose         [internal]
169  */
170 static  DWORD   MCIAVI_drvClose(DWORD dwDevID)
171 {
172     WINE_MCIAVI *wma;
173
174     TRACE("%04lx\n", dwDevID);
175
176     /* finish all outstanding things */
177     MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL);
178
179     wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
180
181     if (wma) {
182         MCIAVI_UnregisterClass();
183
184         EnterCriticalSection(&wma->cs);
185
186         mciSetDriverData(dwDevID, 0);
187         mciFreeCommandResource(wma->wCommandTable);
188
189         CloseHandle(wma->hStopEvent);
190
191         LeaveCriticalSection(&wma->cs);
192         DeleteCriticalSection(&wma->cs);
193
194         HeapFree(GetProcessHeap(), 0, wma);
195         return 1;
196     }
197     return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
198 }
199
200 /**************************************************************************
201  *                              MCIAVI_drvConfigure             [internal]
202  */
203 static  DWORD   MCIAVI_drvConfigure(DWORD dwDevID)
204 {
205     WINE_MCIAVI *wma;
206
207     TRACE("%04lx\n", dwDevID);
208
209     MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);
210
211     wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
212
213     if (wma) {
214         MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
215         return 1;
216     }
217     return 0;
218 }
219
220 /**************************************************************************
221  *                              MCIAVI_mciGetOpenDev            [internal]
222  */
223 WINE_MCIAVI*  MCIAVI_mciGetOpenDev(UINT wDevID)
224 {
225     WINE_MCIAVI*        wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
226
227     if (wma == NULL || wma->nUseCount == 0) {
228         WARN("Invalid wDevID=%u\n", wDevID);
229         return 0;
230     }
231     return wma;
232 }
233
234 static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
235 {
236     /* to prevent handling in WindowProc */
237     wma->dwStatus = MCI_MODE_NOT_READY;
238     if (wma->hFile) {
239         mmioClose(wma->hFile, 0);
240         wma->hFile = 0;
241
242         HeapFree(GetProcessHeap(), 0, wma->lpFileName);
243         wma->lpFileName = NULL;
244
245         HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
246         wma->lpVideoIndex = NULL;
247         HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
248         wma->lpAudioIndex = NULL;
249         if (wma->hic)           ICClose(wma->hic);
250         wma->hic = 0;
251         HeapFree(GetProcessHeap(), 0, wma->inbih);
252         wma->inbih = NULL;
253         HeapFree(GetProcessHeap(), 0, wma->outbih);
254         wma->outbih = NULL;
255         HeapFree(GetProcessHeap(), 0, wma->indata);
256         wma->indata = NULL;
257         HeapFree(GetProcessHeap(), 0, wma->outdata);
258         wma->outdata = NULL;
259         if (wma->hbmFrame)      DeleteObject(wma->hbmFrame);
260         wma->hbmFrame = 0;
261         if (wma->hWnd)          DestroyWindow(wma->hWnd);
262         wma->hWnd = 0;
263
264         HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
265         wma->lpWaveFormat = 0;
266
267         memset(&wma->mah, 0, sizeof(wma->mah));
268         memset(&wma->ash_video, 0, sizeof(wma->ash_video));
269         memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
270         wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
271         wma->dwCachedFrame = -1;
272     }
273 }
274
275 /***************************************************************************
276  *                              MCIAVI_mciOpen                  [internal]
277  */
278 static  DWORD   MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
279                                LPMCI_DGV_OPEN_PARMSW lpOpenParms)
280 {
281     WINE_MCIAVI *wma;
282     LRESULT             dwRet = 0;
283
284     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
285
286     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
287
288     if (lpOpenParms == NULL)            return MCIERR_NULL_PARAMETER_BLOCK;
289
290     wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
291     if (wma == NULL)                    return MCIERR_INVALID_DEVICE_ID;
292
293     EnterCriticalSection(&wma->cs);
294
295     if (wma->nUseCount > 0) {
296         /* The driver is already open on this channel */
297         /* If the driver was opened shareable before and this open specifies */
298         /* shareable then increment the use count */
299         if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
300             ++wma->nUseCount;
301         else
302         {
303             LeaveCriticalSection(&wma->cs);
304             return MCIERR_MUST_USE_SHAREABLE;
305         }
306     } else {
307         wma->nUseCount = 1;
308         wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
309     }
310
311     wma->dwStatus = MCI_MODE_NOT_READY;
312
313     if (dwFlags & MCI_OPEN_ELEMENT) {
314         if (dwFlags & MCI_OPEN_ELEMENT_ID) {
315             /* could it be that (DWORD)lpOpenParms->lpstrElementName
316              * contains the hFile value ?
317              */
318             dwRet = MCIERR_UNRECOGNIZED_COMMAND;
319         } else if (strlenW(lpOpenParms->lpstrElementName) > 0) {
320             /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
321             TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(lpOpenParms->lpstrElementName));
322
323             if (lpOpenParms->lpstrElementName && (strlenW(lpOpenParms->lpstrElementName) > 0))
324             {
325                 wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpOpenParms->lpstrElementName) + 1) * sizeof(WCHAR));
326                 strcpyW(wma->lpFileName, lpOpenParms->lpstrElementName);
327
328                 wma->hFile = mmioOpenW(lpOpenParms->lpstrElementName, NULL,
329                                        MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READ);
330
331                 if (wma->hFile == 0) {
332                     WARN("can't find file=%s!\n", debugstr_w(lpOpenParms->lpstrElementName));
333                     dwRet = MCIERR_FILE_NOT_FOUND;
334                 } else {
335                     if (!MCIAVI_GetInfo(wma))
336                         dwRet = MCIERR_INVALID_FILE;
337                     else if (!MCIAVI_OpenVideo(wma))
338                         dwRet = MCIERR_CANNOT_LOAD_DRIVER;
339                     else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
340                         dwRet = MCIERR_CREATEWINDOW;
341                 }
342             }
343         } else {
344             FIXME("Don't record yet\n");
345             dwRet = MCIERR_UNSUPPORTED_FUNCTION;
346         }
347     }
348
349     if (dwRet == 0) {
350         TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID);
351
352         wma->dwStatus = MCI_MODE_STOP;
353         wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
354     } else {
355         MCIAVI_CleanUp(wma);
356     }
357
358     LeaveCriticalSection(&wma->cs);
359     return dwRet;
360 }
361
362 /***************************************************************************
363  *                              MCIAVI_mciClose                 [internal]
364  */
365 DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
366 {
367     WINE_MCIAVI *wma;
368     DWORD               dwRet = 0;
369
370     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
371
372     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
373
374     wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
375     if (wma == NULL)    return MCIERR_INVALID_DEVICE_ID;
376
377     EnterCriticalSection(&wma->cs);
378
379     if (wma->nUseCount == 1) {
380         if (wma->dwStatus != MCI_MODE_STOP)
381            dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
382         MCIAVI_CleanUp(wma);
383
384         if ((dwFlags & MCI_NOTIFY) && lpParms) {
385             mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
386                            wDevID,
387                             MCI_NOTIFY_SUCCESSFUL);
388         }
389         LeaveCriticalSection(&wma->cs);
390         return dwRet;
391     }
392     wma->nUseCount--;
393
394     LeaveCriticalSection(&wma->cs);
395     return dwRet;
396 }
397
398 /***************************************************************************
399  *                              MCIAVI_mciPlay                  [internal]
400  */
401 static  DWORD   MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
402 {
403     WINE_MCIAVI *wma;
404     DWORD               tc;
405     DWORD               frameTime;
406     DWORD               delta;
407     DWORD               dwRet;
408     LPWAVEHDR           waveHdr = NULL;
409     unsigned            i, nHdr = 0;
410     DWORD               dwFromFrame, dwToFrame;
411
412     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
413
414     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
415
416     wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
417     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
418
419     EnterCriticalSection(&wma->cs);
420
421     if (!wma->hFile)
422     {
423         LeaveCriticalSection(&wma->cs);
424         return MCIERR_FILE_NOT_FOUND;
425     }
426     if (!wma->hWndPaint)
427     {
428         LeaveCriticalSection(&wma->cs);
429         return MCIERR_NO_WINDOW;
430     }
431
432     LeaveCriticalSection(&wma->cs);
433
434     if (!(dwFlags & MCI_WAIT)) {
435        return MCI_SendCommandAsync(wDevID, MCI_PLAY, dwFlags,
436                                    (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
437     }
438
439     if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
440         ShowWindow(wma->hWndPaint, SW_SHOWNA);
441
442     EnterCriticalSection(&wma->cs);
443
444     dwFromFrame = wma->dwCurrVideoFrame;
445     dwToFrame = wma->dwPlayableVideoFrames - 1;
446
447     if (lpParms && (dwFlags & MCI_FROM)) {
448         dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
449     }
450     if (lpParms && (dwFlags & MCI_TO)) {
451         dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
452     }
453     if (dwToFrame >= wma->dwPlayableVideoFrames)
454         dwToFrame = wma->dwPlayableVideoFrames - 1;
455
456     TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame, dwToFrame);
457
458     wma->dwCurrVideoFrame = dwFromFrame;
459     wma->dwToVideoFrame = dwToFrame;
460
461     /* if already playing exit */
462     if (wma->dwStatus == MCI_MODE_PLAY)
463     {
464         LeaveCriticalSection(&wma->cs);
465         return 0;
466     }
467
468     if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
469     {
470         dwRet = 0;
471         goto mci_play_done;
472     }
473
474     wma->dwStatus = MCI_MODE_PLAY;
475
476     if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
477         FIXME("Unsupported flag %08lx\n", dwFlags);
478
479     /* time is in microseconds, we should convert it to milliseconds */
480     frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;
481
482     if (wma->lpWaveFormat) {
483        if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
484         {
485             /* can't play audio */
486             HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
487             wma->lpWaveFormat = NULL;
488         }
489         else
490         /* fill the queue with as many wave headers as possible */
491         MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
492     }
493
494     while (wma->dwStatus == MCI_MODE_PLAY)
495     {
496         HDC hDC;
497
498         tc = GetTickCount();
499
500         hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
501         if (hDC)
502         {
503             MCIAVI_PaintFrame(wma, hDC);
504             ReleaseDC(wma->hWndPaint, hDC);
505         }
506
507         if (wma->lpWaveFormat) {
508             HANDLE events[2];
509             DWORD ret;
510
511             events[0] = wma->hStopEvent;
512             events[1] = wma->hEvent;
513
514             MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
515             delta = GetTickCount() - tc;
516
517             LeaveCriticalSection(&wma->cs);
518             ret = MsgWaitForMultipleObjectsEx(2, events,
519                 (delta >= frameTime) ? 0 : frameTime - delta, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
520             EnterCriticalSection(&wma->cs);
521
522             if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
523         }
524
525         delta = GetTickCount() - tc;
526         if (delta < frameTime)
527         {
528             DWORD ret;
529
530             LeaveCriticalSection(&wma->cs);
531             ret = MsgWaitForMultipleObjectsEx(1, &wma->hStopEvent, frameTime - delta,
532                                               QS_ALLINPUT, MWMO_INPUTAVAILABLE);
533             EnterCriticalSection(&wma->cs);
534             if (ret == WAIT_OBJECT_0) break;
535         }
536
537        if (wma->dwCurrVideoFrame < dwToFrame)
538            wma->dwCurrVideoFrame++;
539         else
540             break;
541     }
542
543     if (wma->lpWaveFormat) {
544        while (wma->dwEventCount != nHdr - 1)
545         {
546             LeaveCriticalSection(&wma->cs);
547             Sleep(100);
548             EnterCriticalSection(&wma->cs);
549         }
550
551         /* just to get rid of some race conditions between play, stop and pause */
552         LeaveCriticalSection(&wma->cs);
553         waveOutReset(wma->hWave);
554         EnterCriticalSection(&wma->cs);
555
556         for (i = 0; i < nHdr; i++)
557             waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
558     }
559
560     dwRet = 0;
561
562     if (wma->lpWaveFormat) {
563         HeapFree(GetProcessHeap(), 0, waveHdr);
564
565         if (wma->hWave) {
566             LeaveCriticalSection(&wma->cs);
567             waveOutClose(wma->hWave);
568             EnterCriticalSection(&wma->cs);
569             wma->hWave = 0;
570         }
571         CloseHandle(wma->hEvent);
572     }
573
574 mci_play_done:
575     wma->dwStatus = MCI_MODE_STOP;
576
577     if (lpParms && (dwFlags & MCI_NOTIFY)) {
578         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
579         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
580                        wDevID, MCI_NOTIFY_SUCCESSFUL);
581     }
582     LeaveCriticalSection(&wma->cs);
583     return dwRet;
584 }
585
586 /***************************************************************************
587  *                              MCIAVI_mciRecord                        [internal]
588  */
589 static  DWORD   MCIAVI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECORD_PARMS lpParms)
590 {
591     WINE_MCIAVI *wma;
592
593     FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
594
595     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
596
597     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
598
599     wma = MCIAVI_mciGetOpenDev(wDevID);
600     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
601
602     EnterCriticalSection(&wma->cs);
603     wma->dwStatus = MCI_MODE_RECORD;
604     LeaveCriticalSection(&wma->cs);
605     return 0;
606 }
607
608 /***************************************************************************
609  *                              MCIAVI_mciStop                  [internal]
610  */
611 static  DWORD   MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
612 {
613     WINE_MCIAVI *wma;
614     DWORD               dwRet = 0;
615
616     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
617
618     wma = MCIAVI_mciGetOpenDev(wDevID);
619     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
620
621     EnterCriticalSection(&wma->cs);
622
623     switch (wma->dwStatus) {
624     case MCI_MODE_PLAY:
625     case MCI_MODE_RECORD:
626         LeaveCriticalSection(&wma->cs);
627         SetEvent(wma->hStopEvent);
628         EnterCriticalSection(&wma->cs);
629         /* fall through */
630     case MCI_MODE_PAUSE:
631         /* Since our wave notification callback takes the lock,
632          * we must release it before resetting the device */
633         LeaveCriticalSection(&wma->cs);
634         dwRet = waveOutReset(wma->hWave);
635         EnterCriticalSection(&wma->cs);
636         /* fall through */
637     default:
638         do /* one more chance for an async thread to finish */
639         {
640             LeaveCriticalSection(&wma->cs);
641             Sleep(10);
642             EnterCriticalSection(&wma->cs);
643         } while (wma->dwStatus != MCI_MODE_STOP);
644
645         break;
646
647     case MCI_MODE_NOT_READY:
648         break;        
649     }
650
651     if ((dwFlags & MCI_NOTIFY) && lpParms) {
652         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
653                        wDevID, MCI_NOTIFY_SUCCESSFUL);
654     }
655     LeaveCriticalSection(&wma->cs);
656     return dwRet;
657 }
658
659 /***************************************************************************
660  *                              MCIAVI_mciPause                 [internal]
661  */
662 static  DWORD   MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
663 {
664     WINE_MCIAVI *wma;
665
666     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
667
668     wma = MCIAVI_mciGetOpenDev(wDevID);
669     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
670
671     EnterCriticalSection(&wma->cs);
672
673     if (wma->dwStatus == MCI_MODE_PLAY)
674         wma->dwStatus = MCI_MODE_PAUSE;
675
676     if (wma->lpWaveFormat) {
677         LeaveCriticalSection(&wma->cs);
678         return waveOutPause(wma->hWave);
679     }
680
681     LeaveCriticalSection(&wma->cs);
682     return 0;
683 }
684
685 /***************************************************************************
686  *                              MCIAVI_mciResume                        [internal]
687  */
688 static  DWORD   MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
689 {
690     WINE_MCIAVI *wma;
691
692     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
693
694     wma = MCIAVI_mciGetOpenDev(wDevID);
695     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
696
697     EnterCriticalSection(&wma->cs);
698
699     if (wma->dwStatus == MCI_MODE_PAUSE)
700         wma->dwStatus = MCI_MODE_PLAY;
701
702     if (wma->lpWaveFormat) {
703         LeaveCriticalSection(&wma->cs);
704         return waveOutRestart(wma->hWave);
705     }
706
707     LeaveCriticalSection(&wma->cs);
708     return 0;
709 }
710
711 /***************************************************************************
712  *                              MCIAVI_mciSeek                  [internal]
713  */
714 static  DWORD   MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
715 {
716     WINE_MCIAVI *wma;
717
718     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
719
720     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
721
722     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
723
724     wma = MCIAVI_mciGetOpenDev(wDevID);
725     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
726
727     EnterCriticalSection(&wma->cs);
728
729     if (dwFlags & MCI_SEEK_TO_START) {
730         wma->dwCurrVideoFrame = 0;
731     } else if (dwFlags & MCI_SEEK_TO_END) {
732         wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
733     } else if (dwFlags & MCI_TO) {
734         if (lpParms->dwTo > wma->dwPlayableVideoFrames - 1)
735             lpParms->dwTo = wma->dwPlayableVideoFrames - 1;
736         wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
737     } else {
738         WARN("dwFlag doesn't tell where to seek to...\n");
739         LeaveCriticalSection(&wma->cs);
740         return MCIERR_MISSING_PARAMETER;
741     }
742
743     TRACE("Seeking to frame=%lu bytes\n", wma->dwCurrVideoFrame);
744
745     if (dwFlags & MCI_NOTIFY) {
746         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
747                        wDevID, MCI_NOTIFY_SUCCESSFUL);
748     }
749     LeaveCriticalSection(&wma->cs);
750     return 0;
751 }
752
753 /*****************************************************************************
754  *                              MCIAVI_mciLoad                  [internal]
755  */
756 static DWORD    MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSW lpParms)
757 {
758     WINE_MCIAVI *wma;
759
760     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
761
762     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
763
764     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
765
766     wma = MCIAVI_mciGetOpenDev(wDevID);
767     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
768
769     return 0;
770 }
771
772 /******************************************************************************
773  *                              MCIAVI_mciSave                  [internal]
774  */
775 static  DWORD   MCIAVI_mciSave(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SAVE_PARMSW lpParms)
776 {
777     WINE_MCIAVI *wma;
778
779     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
780
781     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
782
783     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
784
785     wma = MCIAVI_mciGetOpenDev(wDevID);
786     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
787
788     return 0;
789 }
790
791 /******************************************************************************
792  *                              MCIAVI_mciFreeze                        [internal]
793  */
794 static  DWORD   MCIAVI_mciFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
795 {
796     WINE_MCIAVI *wma;
797
798     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
799
800     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
801
802     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
803
804     wma = MCIAVI_mciGetOpenDev(wDevID);
805     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
806
807     return 0;
808 }
809
810 /******************************************************************************
811  *                              MCIAVI_mciRealize                       [internal]
812  */
813 static  DWORD   MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
814 {
815     WINE_MCIAVI *wma;
816
817     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
818
819     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
820
821     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
822
823     wma = MCIAVI_mciGetOpenDev(wDevID);
824     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
825
826     return 0;
827 }
828
829 /******************************************************************************
830  *                              MCIAVI_mciUnFreeze                      [internal]
831  */
832 static  DWORD   MCIAVI_mciUnFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
833 {
834     WINE_MCIAVI *wma;
835
836     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
837
838     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
839
840     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
841
842     wma = MCIAVI_mciGetOpenDev(wDevID);
843     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
844
845     return 0;
846 }
847
848 /******************************************************************************
849  *                              MCIAVI_mciUpdate                        [internal]
850  */
851 static  DWORD   MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
852 {
853     WINE_MCIAVI *wma;
854
855     TRACE("%04x, %08lx, %p\n", wDevID, dwFlags, lpParms);
856
857     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
858
859     wma = MCIAVI_mciGetOpenDev(wDevID);
860     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
861
862     EnterCriticalSection(&wma->cs);
863
864     if (dwFlags & MCI_DGV_UPDATE_HDC)
865         MCIAVI_PaintFrame(wma, lpParms->hDC);
866
867     LeaveCriticalSection(&wma->cs);
868
869     return 0;
870 }
871
872 /******************************************************************************
873  *                              MCIAVI_mciStep                  [internal]
874  */
875 static  DWORD   MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
876 {
877     WINE_MCIAVI *wma;
878
879     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
880
881     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
882
883     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
884
885     wma = MCIAVI_mciGetOpenDev(wDevID);
886     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
887
888     return 0;
889 }
890
891 /******************************************************************************
892  *                              MCIAVI_mciCopy                  [internal]
893  */
894 static  DWORD   MCIAVI_mciCopy(UINT wDevID, DWORD dwFlags, LPMCI_DGV_COPY_PARMS lpParms)
895 {
896     WINE_MCIAVI *wma;
897
898     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
899
900     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
901
902     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
903
904     wma = MCIAVI_mciGetOpenDev(wDevID);
905     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
906
907     return 0;
908 }
909
910 /******************************************************************************
911  *                              MCIAVI_mciCut                   [internal]
912  */
913 static  DWORD   MCIAVI_mciCut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUT_PARMS lpParms)
914 {
915     WINE_MCIAVI *wma;
916
917     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
918
919     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
920
921     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
922
923     wma = MCIAVI_mciGetOpenDev(wDevID);
924     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
925
926     return 0;
927 }
928
929 /******************************************************************************
930  *                              MCIAVI_mciDelete                        [internal]
931  */
932 static  DWORD   MCIAVI_mciDelete(UINT wDevID, DWORD dwFlags, LPMCI_DGV_DELETE_PARMS lpParms)
933 {
934     WINE_MCIAVI *wma;
935
936     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
937
938     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
939
940     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
941
942     wma = MCIAVI_mciGetOpenDev(wDevID);
943     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
944
945     return 0;
946 }
947
948 /******************************************************************************
949  *                              MCIAVI_mciPaste                 [internal]
950  */
951 static  DWORD   MCIAVI_mciPaste(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PASTE_PARMS lpParms)
952 {
953     WINE_MCIAVI *wma;
954
955     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
956
957     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
958
959     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
960
961     wma = MCIAVI_mciGetOpenDev(wDevID);
962     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
963
964     return 0;
965 }
966
967 /******************************************************************************
968  *                              MCIAVI_mciCue                   [internal]
969  */
970 static  DWORD   MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
971 {
972     WINE_MCIAVI *wma;
973
974     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
975
976     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
977
978     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
979
980     wma = MCIAVI_mciGetOpenDev(wDevID);
981     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
982
983     return 0;
984 }
985
986 /******************************************************************************
987  *                              MCIAVI_mciCapture                       [internal]
988  */
989 static  DWORD   MCIAVI_mciCapture(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CAPTURE_PARMSW lpParms)
990 {
991     WINE_MCIAVI *wma;
992
993     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
994
995     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
996
997     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
998
999     wma = MCIAVI_mciGetOpenDev(wDevID);
1000     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1001
1002     return 0;
1003 }
1004
1005 /******************************************************************************
1006  *                              MCIAVI_mciMonitor                       [internal]
1007  */
1008 static  DWORD   MCIAVI_mciMonitor(UINT wDevID, DWORD dwFlags, LPMCI_DGV_MONITOR_PARMS lpParms)
1009 {
1010     WINE_MCIAVI *wma;
1011
1012     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1013
1014     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1015
1016     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1017
1018     wma = MCIAVI_mciGetOpenDev(wDevID);
1019     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1020
1021     return 0;
1022 }
1023
1024 /******************************************************************************
1025  *                              MCIAVI_mciReserve                       [internal]
1026  */
1027 static  DWORD   MCIAVI_mciReserve(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESERVE_PARMSW lpParms)
1028 {
1029     WINE_MCIAVI *wma;
1030
1031     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1032
1033     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1034
1035     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1036
1037     wma = MCIAVI_mciGetOpenDev(wDevID);
1038     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1039
1040     return 0;
1041 }
1042
1043 /******************************************************************************
1044  *                              MCIAVI_mciSetAudio                      [internal]
1045  */
1046 static  DWORD   MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms)
1047 {
1048     WINE_MCIAVI *wma;
1049
1050     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1051
1052     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1053
1054     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1055
1056     wma = MCIAVI_mciGetOpenDev(wDevID);
1057     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1058
1059     return 0;
1060 }
1061
1062 /******************************************************************************
1063  *                              MCIAVI_mciSignal                        [internal]
1064  */
1065 static  DWORD   MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
1066 {
1067     WINE_MCIAVI *wma;
1068
1069     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1070
1071     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1072
1073     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1074
1075     wma = MCIAVI_mciGetOpenDev(wDevID);
1076     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1077
1078     return 0;
1079 }
1080
1081 /******************************************************************************
1082  *                              MCIAVI_mciSetVideo                      [internal]
1083  */
1084 static  DWORD   MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSW lpParms)
1085 {
1086     WINE_MCIAVI *wma;
1087
1088     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1089
1090     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1091
1092     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1093
1094     wma = MCIAVI_mciGetOpenDev(wDevID);
1095     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1096
1097     return 0;
1098 }
1099
1100 /******************************************************************************
1101  *                              MCIAVI_mciQuality                       [internal]
1102  */
1103 static  DWORD   MCIAVI_mciQuality(UINT wDevID, DWORD dwFlags, LPMCI_DGV_QUALITY_PARMSW lpParms)
1104 {
1105     WINE_MCIAVI *wma;
1106
1107     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1108
1109     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1110
1111     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1112
1113     wma = MCIAVI_mciGetOpenDev(wDevID);
1114     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1115
1116     return 0;
1117 }
1118
1119 /******************************************************************************
1120  *                              MCIAVI_mciList                  [internal]
1121  */
1122 static  DWORD   MCIAVI_mciList(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LIST_PARMSW lpParms)
1123 {
1124     WINE_MCIAVI *wma;
1125
1126     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1127
1128     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1129
1130     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1131
1132     wma = MCIAVI_mciGetOpenDev(wDevID);
1133     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1134
1135     return 0;
1136 }
1137
1138 /******************************************************************************
1139  *                              MCIAVI_mciUndo                  [internal]
1140  */
1141 static  DWORD   MCIAVI_mciUndo(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
1142 {
1143     WINE_MCIAVI *wma;
1144
1145     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1146
1147     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1148
1149     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1150
1151     wma = MCIAVI_mciGetOpenDev(wDevID);
1152     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1153
1154     return 0;
1155 }
1156
1157 /******************************************************************************
1158  *                              MCIAVI_mciConfigure                     [internal]
1159  */
1160 static  DWORD   MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
1161 {
1162     WINE_MCIAVI *wma;
1163
1164     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1165
1166     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1167
1168     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1169
1170     wma = MCIAVI_mciGetOpenDev(wDevID);
1171     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1172
1173     return 0;
1174 }
1175
1176 /******************************************************************************
1177  *                              MCIAVI_mciRestore                       [internal]
1178  */
1179 static  DWORD   MCIAVI_mciRestore(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARMSW lpParms)
1180 {
1181     WINE_MCIAVI *wma;
1182
1183     FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
1184
1185     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
1186
1187     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
1188
1189     wma = MCIAVI_mciGetOpenDev(wDevID);
1190     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
1191
1192     return 0;
1193 }
1194
1195 /*======================================================================*
1196  *                          MCI AVI entry points                        *
1197  *======================================================================*/
1198
1199 /**************************************************************************
1200  *                              DriverProc (MCIAVI.@)
1201  */
1202 LONG CALLBACK   MCIAVI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
1203                                   DWORD dwParam1, DWORD dwParam2)
1204 {
1205     TRACE("(%08lX, %p, %08lX, %08lX, %08lX)\n",
1206           dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1207
1208     switch (wMsg) {
1209     case DRV_LOAD:              return 1;
1210     case DRV_FREE:              return 1;
1211     case DRV_OPEN:              return MCIAVI_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2);
1212     case DRV_CLOSE:             return MCIAVI_drvClose(dwDevID);
1213     case DRV_ENABLE:            return 1;
1214     case DRV_DISABLE:           return 1;
1215     case DRV_QUERYCONFIGURE:    return 1;
1216     case DRV_CONFIGURE:         return MCIAVI_drvConfigure(dwDevID);
1217     case DRV_INSTALL:           return DRVCNF_RESTART;
1218     case DRV_REMOVE:            return DRVCNF_RESTART;
1219     }
1220
1221     /* session instance */
1222     if (dwDevID == 0xFFFFFFFF) return 1;
1223
1224     switch (wMsg) {
1225     case MCI_OPEN_DRIVER:       return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW)     dwParam2);
1226     case MCI_CLOSE_DRIVER:      return MCIAVI_mciClose     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1227     case MCI_PLAY:              return MCIAVI_mciPlay      (dwDevID, dwParam1, (LPMCI_PLAY_PARMS)          dwParam2);
1228     case MCI_RECORD:            return MCIAVI_mciRecord    (dwDevID, dwParam1, (LPMCI_DGV_RECORD_PARMS)    dwParam2);
1229     case MCI_STOP:              return MCIAVI_mciStop      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1230     case MCI_SET:               return MCIAVI_mciSet       (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS)       dwParam2);
1231     case MCI_PAUSE:             return MCIAVI_mciPause     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1232     case MCI_RESUME:            return MCIAVI_mciResume    (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1233     case MCI_STATUS:            return MCIAVI_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW)   dwParam2);
1234     case MCI_GETDEVCAPS:        return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
1235     case MCI_INFO:              return MCIAVI_mciInfo      (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW)     dwParam2);
1236     case MCI_SEEK:              return MCIAVI_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
1237     case MCI_PUT:               return MCIAVI_mciPut       (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS)       dwParam2);
1238     case MCI_WINDOW:            return MCIAVI_mciWindow    (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW)   dwParam2);
1239     case MCI_LOAD:              return MCIAVI_mciLoad      (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSW)     dwParam2);
1240     case MCI_SAVE:              return MCIAVI_mciSave      (dwDevID, dwParam1, (LPMCI_DGV_SAVE_PARMSW)     dwParam2);
1241     case MCI_FREEZE:            return MCIAVI_mciFreeze    (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
1242     case MCI_REALIZE:           return MCIAVI_mciRealize   (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1243     case MCI_UNFREEZE:          return MCIAVI_mciUnFreeze  (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
1244     case MCI_UPDATE:            return MCIAVI_mciUpdate    (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)    dwParam2);
1245     case MCI_WHERE:             return MCIAVI_mciWhere     (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
1246     case MCI_STEP:              return MCIAVI_mciStep      (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS)      dwParam2);
1247     case MCI_COPY:              return MCIAVI_mciCopy      (dwDevID, dwParam1, (LPMCI_DGV_COPY_PARMS)      dwParam2);
1248     case MCI_CUT:               return MCIAVI_mciCut       (dwDevID, dwParam1, (LPMCI_DGV_CUT_PARMS)       dwParam2);
1249     case MCI_DELETE:            return MCIAVI_mciDelete    (dwDevID, dwParam1, (LPMCI_DGV_DELETE_PARMS)    dwParam2);
1250     case MCI_PASTE:             return MCIAVI_mciPaste     (dwDevID, dwParam1, (LPMCI_DGV_PASTE_PARMS)     dwParam2);
1251     case MCI_CUE:               return MCIAVI_mciCue       (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS)       dwParam2);
1252         /* Digital Video specific */
1253     case MCI_CAPTURE:           return MCIAVI_mciCapture   (dwDevID, dwParam1, (LPMCI_DGV_CAPTURE_PARMSW)  dwParam2);
1254     case MCI_MONITOR:           return MCIAVI_mciMonitor   (dwDevID, dwParam1, (LPMCI_DGV_MONITOR_PARMS)   dwParam2);
1255     case MCI_RESERVE:           return MCIAVI_mciReserve   (dwDevID, dwParam1, (LPMCI_DGV_RESERVE_PARMSW)  dwParam2);
1256     case MCI_SETAUDIO:          return MCIAVI_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
1257     case MCI_SIGNAL:            return MCIAVI_mciSignal    (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS)    dwParam2);
1258     case MCI_SETVIDEO:          return MCIAVI_mciSetVideo  (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSW) dwParam2);
1259     case MCI_QUALITY:           return MCIAVI_mciQuality   (dwDevID, dwParam1, (LPMCI_DGV_QUALITY_PARMSW)  dwParam2);
1260     case MCI_LIST:              return MCIAVI_mciList      (dwDevID, dwParam1, (LPMCI_DGV_LIST_PARMSW)     dwParam2);
1261     case MCI_UNDO:              return MCIAVI_mciUndo      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1262     case MCI_CONFIGURE:         return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1263     case MCI_RESTORE:           return MCIAVI_mciRestore   (dwDevID, dwParam1, (LPMCI_DGV_RESTORE_PARMSW)  dwParam2);
1264
1265     case MCI_SPIN:
1266     case MCI_ESCAPE:
1267         WARN("Unsupported command [%lu]\n", wMsg);
1268         break;
1269     case MCI_OPEN:
1270     case MCI_CLOSE:
1271         FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1272         break;
1273     default:
1274         TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
1275         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1276     }
1277     return MCIERR_UNRECOGNIZED_COMMAND;
1278 }