1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * Digital video MCI Wine Driver
6 * Copyright 1999, 2000 Eric POUECH
10 * - handling of palettes
11 * - recording (which input devices ?), a cam recorder ?
12 * - lots of messages still need to be handled (cf FIXME)
13 * - synchronization between audio and video (especially for interleaved
15 * - synchronization (as in all the Wine MCI drivers (MCI_WAIT) messages)
16 * - robustness when reading file can be enhanced
17 * - better move the AVI handling part to avifile DLL and make use of it
18 * - some files appear to have more than one audio stream (we only play the
20 * - some files contain an index of audio/video frame. Better use it,
21 * instead of rebuilding it
22 * - mciWindow (for setting the hWnd) is broken with media player
23 * - stopping while playing a file with sound blocks until all buffered
24 * audio is played... still should be stopped ASAP
28 #include "private_mciavi.h"
29 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(mciavi);
33 /* ===================================================================
34 * ===================================================================
35 * FIXME: should be using the new mmThreadXXXX functions from WINMM
37 * it would require to add a wine internal flag to mmThreadCreate
38 * in order to pass a 32 bit function instead of a 16 bit one
39 * ===================================================================
40 * =================================================================== */
49 /**************************************************************************
50 * MCI_SCAStarter [internal]
52 static DWORD CALLBACK MCI_SCAStarter(LPVOID arg)
54 struct SCA* sca = (struct SCA*)arg;
57 TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",
58 sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
59 ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
60 TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",
61 sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
62 HeapFree(GetProcessHeap(), 0, sca);
64 WARN("Should not happen ? what's wrong \n");
65 /* should not go after this point */
69 /**************************************************************************
70 * MCI_SendCommandAsync [internal]
72 static DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,
73 DWORD dwParam2, UINT size)
75 struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
78 return MCIERR_OUT_OF_MEMORY;
82 sca->dwParam1 = dwParam1;
84 if (size && dwParam2) {
85 sca->dwParam2 = (DWORD)sca + sizeof(struct SCA);
86 /* copy structure passed by program in dwParam2 to be sure
87 * we can still use it whatever the program does
89 memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
91 sca->dwParam2 = dwParam2;
94 if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {
95 WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
96 return MCI_SCAStarter(&sca);
101 /*======================================================================*
102 * MCI AVI implemantation *
103 *======================================================================*/
105 HINSTANCE MCIAVI_hInstance = 0;
107 BOOL WINAPI MCIAVI_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
110 case DLL_PROCESS_ATTACH:
111 MCIAVI_hInstance = hInstDLL;
117 /**************************************************************************
118 * MCIAVI_drvOpen [internal]
120 static DWORD MCIAVI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
122 WINE_MCIAVI* wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
123 static WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
128 wma->wDevID = modp->wDeviceID;
129 mciSetDriverData(wma->wDevID, (DWORD)wma);
130 wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
131 modp->wCustomCommandTable = wma->wCommandTable;
132 modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
133 return modp->wDeviceID;
136 /**************************************************************************
137 * MCIAVI_drvClose [internal]
139 static DWORD MCIAVI_drvClose(DWORD dwDevID)
141 WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
144 mciSetDriverData(dwDevID, 0);
145 mciFreeCommandResource(wma->wCommandTable);
146 HeapFree(GetProcessHeap(), 0, wma);
152 /**************************************************************************
153 * MCIAVI_drvConfigure [internal]
155 static DWORD MCIAVI_drvConfigure(DWORD dwDevID)
157 WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
160 MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
166 /**************************************************************************
167 * MCIAVI_mciGetOpenDev [internal]
169 WINE_MCIAVI* MCIAVI_mciGetOpenDev(UINT wDevID)
171 WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
173 if (wma == NULL || wma->nUseCount == 0) {
174 WARN("Invalid wDevID=%u\n", wDevID);
180 static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
182 /* to prevent handling in WindowProc */
183 wma->dwStatus = MCI_MODE_NOT_READY;
185 mmioClose(wma->hFile, 0);
187 if (wma->lpVideoIndex) HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
188 wma->lpVideoIndex = NULL;
189 if (wma->lpAudioIndex) HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
190 wma->lpAudioIndex = NULL;
191 if (wma->hic) ICClose(wma->hic);
193 if (wma->inbih) HeapFree(GetProcessHeap(), 0, wma->inbih);
195 if (wma->outbih) HeapFree(GetProcessHeap(), 0, wma->outbih);
197 if (wma->indata) HeapFree(GetProcessHeap(), 0, wma->indata);
199 if (wma->outdata) HeapFree(GetProcessHeap(), 0, wma->outdata);
201 if (wma->hbmFrame) DeleteObject(wma->hbmFrame);
203 if (wma->hWnd) DestroyWindow(wma->hWnd);
206 if (wma->lpWaveFormat) HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
207 wma->lpWaveFormat = 0;
209 memset(&wma->mah, 0, sizeof(wma->mah));
210 memset(&wma->ash_video, 0, sizeof(wma->ash_video));
211 memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
212 wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
216 static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
218 /***************************************************************************
219 * MCIAVI_mciOpen [internal]
221 static DWORD MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
222 LPMCI_DGV_OPEN_PARMSA lpOpenParms)
224 WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
227 TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);
229 if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
230 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
232 if (wma->nUseCount > 0) {
233 /* The driver is already open on this channel */
234 /* If the driver was opened shareable before and this open specifies */
235 /* shareable then increment the use count */
236 if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
239 return MCIERR_MUST_USE_SHAREABLE;
242 wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
245 wma->dwStatus = MCI_MODE_NOT_READY;
246 InitializeCriticalSection(&wma->cs);
248 if (dwFlags & MCI_OPEN_ELEMENT) {
249 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
250 /* could it be that (DWORD)lpOpenParms->lpstrElementName
251 * contains the hFile value ?
253 dwRet = MCIERR_UNRECOGNIZED_COMMAND;
254 } else if (strlen(lpOpenParms->lpstrElementName) > 0) {
255 /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
256 TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms->lpstrElementName);
258 if (lpOpenParms->lpstrElementName && (strlen(lpOpenParms->lpstrElementName) > 0)) {
259 wma->hFile = mmioOpenA(lpOpenParms->lpstrElementName, NULL,
260 MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READWRITE);
262 if (wma->hFile == 0) {
263 WARN("can't find file='%s' !\n", lpOpenParms->lpstrElementName);
264 dwRet = MCIERR_FILE_NOT_FOUND;
266 if (!MCIAVI_GetInfo(wma))
267 dwRet = MCIERR_INVALID_FILE;
268 else if (!MCIAVI_OpenVideo(wma))
269 dwRet = MCIERR_CANNOT_LOAD_DRIVER;
270 else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
271 dwRet = MCIERR_CREATEWINDOW;
275 FIXME("Don't record yet\n");
276 dwRet = MCIERR_UNSUPPORTED_FUNCTION;
280 memcpy(&wma->openParms, lpOpenParms, sizeof(MCI_WAVE_OPEN_PARMSA));
283 wma->dwStatus = MCI_MODE_STOP;
284 wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
292 /***************************************************************************
293 * MCIAVI_mciClose [internal]
295 static DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
297 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
300 TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
302 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
304 if (wma->nUseCount == 1) {
305 if (wma->dwStatus != MCI_MODE_STOP)
306 dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, lpParms);
309 if ((dwFlags & MCI_NOTIFY) && lpParms) {
310 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
311 wma->openParms.wDeviceID,
312 MCI_NOTIFY_SUCCESSFUL);
314 HeapFree(GetProcessHeap(), 0, wma);
321 /***************************************************************************
322 * MCIAVI_mciPlay [internal]
324 static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
326 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
331 LPWAVEHDR waveHdr = NULL;
332 unsigned i, nHdr = 0;
333 DWORD dwFromFrame, dwToFrame;
335 TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
337 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
338 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
340 if (!wma->hFile) return MCIERR_FILE_NOT_FOUND;
341 if (!wma->hWnd) return MCIERR_NO_WINDOW;
343 wma->dwStatus = MCI_MODE_PLAY;
345 if (!(dwFlags & MCI_WAIT)) {
346 return MCI_SendCommandAsync(wma->openParms.wDeviceID, MCI_PLAY, dwFlags,
347 (DWORD)lpParms, sizeof(MCI_PLAY_PARMS));
350 ShowWindow(wma->hWnd, SW_SHOW);
352 dwFromFrame = wma->dwCurrVideoFrame;
353 dwToFrame = wma->dwPlayableVideoFrames - 1;
355 if (lpParms && (dwFlags & MCI_FROM)) {
356 dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
358 if (lpParms && (dwFlags & MCI_TO)) {
359 dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
361 if (dwToFrame >= wma->dwPlayableVideoFrames)
362 dwToFrame = wma->dwPlayableVideoFrames - 1;
364 TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame, dwToFrame);
366 if (dwToFrame <= wma->dwCurrVideoFrame)
368 wma->dwCurrVideoFrame = dwFromFrame;
370 if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
371 FIXME("Unsupported flag %08lx\n", dwFlags);
373 /* time is in microseconds, we should convert it to milliseconds */
374 frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;
376 if (wma->lpWaveFormat) {
377 if ((dwRet = MCIAVI_OpenAudio(wma, &nHdr, &waveHdr)) != 0)
379 /* fill the queue with as many wave headers as possible */
380 MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
383 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY) {
386 MCIAVI_DrawFrame(wma);
388 if (wma->lpWaveFormat) {
389 MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
390 delta = GetTickCount() - tc;
391 WaitForSingleObject(wma->hEvent, (delta >= frameTime) ? 0 : frameTime - delta);
394 delta = GetTickCount() - tc;
395 if (delta < frameTime)
396 Sleep(frameTime - delta);
398 if (wma->dwCurrVideoFrame++ >= dwToFrame) {
399 wma->dwCurrVideoFrame--;
400 wma->dwStatus = MCI_MODE_STOP;
404 if (wma->lpWaveFormat) {
405 while (*(volatile DWORD*)&wma->dwEventCount != nHdr - 1) {
409 /* just to get rid of some race conditions between play, stop and pause */
410 waveOutReset(wma->hWave);
412 for (i = 0; i < nHdr; i++)
413 waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
418 if (wma->lpWaveFormat) {
419 HeapFree(GetProcessHeap(), 0, waveHdr);
422 waveOutClose(wma->hWave);
425 CloseHandle(wma->hEvent);
428 if (lpParms && (dwFlags & MCI_NOTIFY)) {
429 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
430 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
431 wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
434 wma->dwStatus = MCI_MODE_STOP;
439 /***************************************************************************
440 * MCIAVI_mciRecord [internal]
442 static DWORD MCIAVI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECORD_PARMS lpParms)
444 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
446 FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
448 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
449 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
451 wma->dwStatus = MCI_MODE_RECORD;
455 /***************************************************************************
456 * MCIAVI_mciStop [internal]
458 static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
460 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
463 TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
465 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
466 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
468 switch (wma->dwStatus) {
471 case MCI_MODE_RECORD:
473 int oldStat = wma->dwStatus;
474 wma->dwStatus = MCI_MODE_NOT_READY;
475 if (oldStat == MCI_MODE_PAUSE)
476 dwRet = waveOutReset(wma->hWave);
478 while (wma->dwStatus != MCI_MODE_STOP)
482 wma->dwStatus = MCI_MODE_STOP;
486 if ((dwFlags & MCI_NOTIFY) && lpParms) {
487 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
488 wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
494 /***************************************************************************
495 * MCIAVI_mciPause [internal]
497 static DWORD MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
499 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
501 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
502 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
504 if (wma->dwStatus == MCI_MODE_PLAY)
505 wma->dwStatus = MCI_MODE_PAUSE;
507 return (wma->lpWaveFormat) ? waveOutPause(wma->hWave) : 0;
510 /***************************************************************************
511 * MCIAVI_mciResume [internal]
513 static DWORD MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
515 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
517 FIXME("(%04x, %08lX, %p) : stub\n", wDevID, dwFlags, lpParms);
519 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
520 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
522 if (wma->dwStatus == MCI_MODE_PAUSE)
523 wma->dwStatus = MCI_MODE_PLAY;
525 return (wma->lpWaveFormat) ? waveOutRestart(wma->hWave) : 0;
528 /***************************************************************************
529 * MCIAVI_mciSeek [internal]
531 static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
533 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
535 TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
537 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
538 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
540 EnterCriticalSection(&wma->cs);
542 MCIAVI_mciStop(wDevID, MCI_WAIT, 0);
544 if (dwFlags & MCI_SEEK_TO_START) {
545 wma->dwCurrVideoFrame = 0;
546 } else if (dwFlags & MCI_SEEK_TO_END) {
547 wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
548 } else if (dwFlags & MCI_TO) {
549 wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
551 WARN("dwFlag doesn't tell where to seek to...\n");
552 return MCIERR_MISSING_PARAMETER;
555 TRACE("Seeking to frame=%lu bytes\n", wma->dwCurrVideoFrame);
557 if (dwFlags & MCI_NOTIFY) {
558 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
559 wma->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);
562 LeaveCriticalSection(&wma->cs);
567 /*****************************************************************************
568 * MCIAVI_mciLoad [internal]
570 static DWORD MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSA lpParms)
572 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
574 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
576 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
577 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
582 /******************************************************************************
583 * MCIAVI_mciSave [internal]
585 static DWORD MCIAVI_mciSave(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SAVE_PARMSA lpParms)
587 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
589 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
591 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
592 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
597 /******************************************************************************
598 * MCIAVI_mciFreeze [internal]
600 static DWORD MCIAVI_mciFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
602 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
604 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
606 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
607 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
612 /******************************************************************************
613 * MCIAVI_mciRealize [internal]
615 static DWORD MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
617 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
619 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
621 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
622 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
627 /******************************************************************************
628 * MCIAVI_mciUnFreeze [internal]
630 static DWORD MCIAVI_mciUnFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
632 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
634 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
636 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
637 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
642 /******************************************************************************
643 * MCIAVI_mciUpdate [internal]
645 static DWORD MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
647 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
649 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
651 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
652 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
657 /******************************************************************************
658 * MCIAVI_mciStep [internal]
660 static DWORD MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
662 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
664 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
666 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
667 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
672 /******************************************************************************
673 * MCIAVI_mciCopy [internal]
675 static DWORD MCIAVI_mciCopy(UINT wDevID, DWORD dwFlags, LPMCI_DGV_COPY_PARMS lpParms)
677 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
679 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
681 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
682 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
687 /******************************************************************************
688 * MCIAVI_mciCut [internal]
690 static DWORD MCIAVI_mciCut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUT_PARMS lpParms)
692 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
694 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
696 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
697 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
702 /******************************************************************************
703 * MCIAVI_mciDelete [internal]
705 static DWORD MCIAVI_mciDelete(UINT wDevID, DWORD dwFlags, LPMCI_DGV_DELETE_PARMS lpParms)
707 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
709 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
711 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
712 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
717 /******************************************************************************
718 * MCIAVI_mciPaste [internal]
720 static DWORD MCIAVI_mciPaste(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PASTE_PARMS lpParms)
722 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
724 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
726 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
727 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
732 /******************************************************************************
733 * MCIAVI_mciCue [internal]
735 static DWORD MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
737 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
739 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
741 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
742 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
747 /******************************************************************************
748 * MCIAVI_mciCapture [internal]
750 static DWORD MCIAVI_mciCapture(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CAPTURE_PARMSA lpParms)
752 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
754 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
756 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
757 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
762 /******************************************************************************
763 * MCIAVI_mciMonitor [internal]
765 static DWORD MCIAVI_mciMonitor(UINT wDevID, DWORD dwFlags, LPMCI_DGV_MONITOR_PARMS lpParms)
767 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
769 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
771 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
772 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
777 /******************************************************************************
778 * MCIAVI_mciReserve [internal]
780 static DWORD MCIAVI_mciReserve(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESERVE_PARMSA lpParms)
782 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
784 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
786 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
787 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
792 /******************************************************************************
793 * MCIAVI_mciSetAudio [internal]
795 static DWORD MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSA lpParms)
797 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
799 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
801 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
802 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
807 /******************************************************************************
808 * MCIAVI_mciSignal [internal]
810 static DWORD MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
812 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
814 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
816 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
817 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
822 /******************************************************************************
823 * MCIAVI_mciSetVideo [internal]
825 static DWORD MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSA lpParms)
827 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
829 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
831 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
832 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
837 /******************************************************************************
838 * MCIAVI_mciQuality [internal]
840 static DWORD MCIAVI_mciQuality(UINT wDevID, DWORD dwFlags, LPMCI_DGV_QUALITY_PARMSA lpParms)
842 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
844 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
846 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
847 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
852 /******************************************************************************
853 * MCIAVI_mciList [internal]
855 static DWORD MCIAVI_mciList(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LIST_PARMSA lpParms)
857 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
859 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
861 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
862 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
867 /******************************************************************************
868 * MCIAVI_mciUndo [internal]
870 static DWORD MCIAVI_mciUndo(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
872 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
874 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
876 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
877 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
882 /******************************************************************************
883 * MCIAVI_mciConfigure [internal]
885 static DWORD MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
887 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
889 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
891 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
892 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
897 /******************************************************************************
898 * MCIAVI_mciRestore [internal]
900 static DWORD MCIAVI_mciRestore(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARMSA lpParms)
902 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID);
904 FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
906 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
907 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
912 /*======================================================================*
913 * MCI AVI entry points *
914 *======================================================================*/
916 /**************************************************************************
917 * MCIAVI_DriverProc [sample driver]
919 LONG CALLBACK MCIAVI_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
920 DWORD dwParam1, DWORD dwParam2)
922 TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",
923 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
926 case DRV_LOAD: return 1;
927 case DRV_FREE: return 1;
928 case DRV_OPEN: return MCIAVI_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
929 case DRV_CLOSE: return MCIAVI_drvClose(dwDevID);
930 case DRV_ENABLE: return 1;
931 case DRV_DISABLE: return 1;
932 case DRV_QUERYCONFIGURE: return 1;
933 case DRV_CONFIGURE: return MCIAVI_drvConfigure(dwDevID);
934 case DRV_INSTALL: return DRVCNF_RESTART;
935 case DRV_REMOVE: return DRVCNF_RESTART;
937 case MCI_OPEN_DRIVER: return MCIAVI_mciOpen (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSA) dwParam2);
938 case MCI_CLOSE_DRIVER: return MCIAVI_mciClose (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
939 case MCI_PLAY: return MCIAVI_mciPlay (dwDevID, dwParam1, (LPMCI_PLAY_PARMS) dwParam2);
940 case MCI_RECORD: return MCIAVI_mciRecord (dwDevID, dwParam1, (LPMCI_DGV_RECORD_PARMS) dwParam2);
941 case MCI_STOP: return MCIAVI_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
942 case MCI_SET: return MCIAVI_mciSet (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS) dwParam2);
943 case MCI_PAUSE: return MCIAVI_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
944 case MCI_RESUME: return MCIAVI_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
945 case MCI_STATUS: return MCIAVI_mciStatus (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSA) dwParam2);
946 case MCI_GETDEVCAPS: return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS) dwParam2);
947 case MCI_INFO: return MCIAVI_mciInfo (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSA) dwParam2);
948 case MCI_SEEK: return MCIAVI_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2);
949 case MCI_PUT: return MCIAVI_mciPut (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS) dwParam2);
950 case MCI_WINDOW: return MCIAVI_mciWindow (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSA) dwParam2);
951 case MCI_LOAD: return MCIAVI_mciLoad (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSA) dwParam2);
952 case MCI_SAVE: return MCIAVI_mciSave (dwDevID, dwParam1, (LPMCI_DGV_SAVE_PARMSA) dwParam2);
953 case MCI_FREEZE: return MCIAVI_mciFreeze (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2);
954 case MCI_REALIZE: return MCIAVI_mciRealize (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
955 case MCI_UNFREEZE: return MCIAVI_mciUnFreeze (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2);
956 case MCI_UPDATE: return MCIAVI_mciUpdate (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS) dwParam2);
957 case MCI_WHERE: return MCIAVI_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2);
958 case MCI_STEP: return MCIAVI_mciStep (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS) dwParam2);
959 case MCI_COPY: return MCIAVI_mciCopy (dwDevID, dwParam1, (LPMCI_DGV_COPY_PARMS) dwParam2);
960 case MCI_CUT: return MCIAVI_mciCut (dwDevID, dwParam1, (LPMCI_DGV_CUT_PARMS) dwParam2);
961 case MCI_DELETE: return MCIAVI_mciDelete (dwDevID, dwParam1, (LPMCI_DGV_DELETE_PARMS) dwParam2);
962 case MCI_PASTE: return MCIAVI_mciPaste (dwDevID, dwParam1, (LPMCI_DGV_PASTE_PARMS) dwParam2);
963 case MCI_CUE: return MCIAVI_mciCue (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS) dwParam2);
964 /* Digital Video specific */
965 case MCI_CAPTURE: return MCIAVI_mciCapture (dwDevID, dwParam1, (LPMCI_DGV_CAPTURE_PARMSA) dwParam2);
966 case MCI_MONITOR: return MCIAVI_mciMonitor (dwDevID, dwParam1, (LPMCI_DGV_MONITOR_PARMS) dwParam2);
967 case MCI_RESERVE: return MCIAVI_mciReserve (dwDevID, dwParam1, (LPMCI_DGV_RESERVE_PARMSA) dwParam2);
968 case MCI_SETAUDIO: return MCIAVI_mciSetAudio (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSA) dwParam2);
969 case MCI_SIGNAL: return MCIAVI_mciSignal (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS) dwParam2);
970 case MCI_SETVIDEO: return MCIAVI_mciSetVideo (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSA) dwParam2);
971 case MCI_QUALITY: return MCIAVI_mciQuality (dwDevID, dwParam1, (LPMCI_DGV_QUALITY_PARMSA) dwParam2);
972 case MCI_LIST: return MCIAVI_mciList (dwDevID, dwParam1, (LPMCI_DGV_LIST_PARMSA) dwParam2);
973 case MCI_UNDO: return MCIAVI_mciUndo (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
974 case MCI_CONFIGURE: return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
975 case MCI_RESTORE: return MCIAVI_mciRestore (dwDevID, dwParam1, (LPMCI_DGV_RESTORE_PARMSA) dwParam2);
979 WARN("Unsupported command [%lu]\n", wMsg);
983 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
986 TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
987 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
989 return MCIERR_UNRECOGNIZED_COMMAND;