1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * Digital video MCI Wine Driver
6 * Copyright 1999, 2000 Eric POUECH
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * - handling of palettes
25 * - recording (which input devices ?), a cam recorder ?
26 * - lots of messages still need to be handled (cf FIXME)
27 * - synchronization between audio and video (especially for interleaved
29 * - synchronization (as in all the Wine MCI drivers (MCI_WAIT) messages)
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
34 * - some files contain an index of audio/video frame. Better use it,
35 * instead of rebuilding it
36 * - mciWindow (for setting the hWnd) is broken with media player
37 * - stopping while playing a file with sound blocks until all buffered
38 * audio is played... still should be stopped ASAP
42 #include "private_mciavi.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(mciavi
);
47 /* ===================================================================
48 * ===================================================================
49 * FIXME: should be using the new mmThreadXXXX functions from WINMM
51 * it would require to add a wine internal flag to mmThreadCreate
52 * in order to pass a 32 bit function instead of a 16 bit one
53 * ===================================================================
54 * =================================================================== */
63 /**************************************************************************
64 * MCI_SCAStarter [internal]
66 static DWORD CALLBACK
MCI_SCAStarter(LPVOID arg
)
68 struct SCA
* sca
= (struct SCA
*)arg
;
71 TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",
72 sca
->wDevID
, sca
->wMsg
, sca
->dwParam1
, sca
->dwParam2
);
73 ret
= mciSendCommandA(sca
->wDevID
, sca
->wMsg
, sca
->dwParam1
| MCI_WAIT
, sca
->dwParam2
);
74 TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",
75 sca
->wDevID
, sca
->wMsg
, sca
->dwParam1
, sca
->dwParam2
);
76 HeapFree(GetProcessHeap(), 0, sca
);
78 WARN("Should not happen ? what's wrong \n");
79 /* should not go after this point */
83 /**************************************************************************
84 * MCI_SendCommandAsync [internal]
86 static DWORD
MCI_SendCommandAsync(UINT wDevID
, UINT wMsg
, DWORD dwParam1
,
87 DWORD dwParam2
, UINT size
)
89 struct SCA
* sca
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA
) + size
);
92 return MCIERR_OUT_OF_MEMORY
;
96 sca
->dwParam1
= dwParam1
;
98 if (size
&& dwParam2
) {
99 sca
->dwParam2
= (DWORD
)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
103 memcpy((LPVOID
)sca
->dwParam2
, (LPVOID
)dwParam2
, size
);
105 sca
->dwParam2
= dwParam2
;
108 if (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
);
115 /*======================================================================*
116 * MCI AVI implemantation *
117 *======================================================================*/
119 HINSTANCE MCIAVI_hInstance
= 0;
121 BOOL WINAPI
MCIAVI_LibMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
124 case DLL_PROCESS_ATTACH
:
125 MCIAVI_hInstance
= hInstDLL
;
131 /**************************************************************************
132 * MCIAVI_drvOpen [internal]
134 static DWORD
MCIAVI_drvOpen(LPSTR str
, LPMCI_OPEN_DRIVER_PARMSA modp
)
137 static WCHAR mciAviWStr
[] = {'M','C','I','A','V','I',0};
139 if (!modp
) return 0xFFFFFFFF;
141 wma
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WINE_MCIAVI
));
145 wma
->wDevID
= modp
->wDeviceID
;
146 mciSetDriverData(wma
->wDevID
, (DWORD
)wma
);
147 wma
->wCommandTable
= mciLoadCommandResource(MCIAVI_hInstance
, mciAviWStr
, 0);
148 modp
->wCustomCommandTable
= wma
->wCommandTable
;
149 modp
->wType
= MCI_DEVTYPE_DIGITAL_VIDEO
;
150 return modp
->wDeviceID
;
153 /**************************************************************************
154 * MCIAVI_drvClose [internal]
156 static DWORD
MCIAVI_drvClose(DWORD dwDevID
)
158 WINE_MCIAVI
* wma
= (WINE_MCIAVI
*)mciGetDriverData(dwDevID
);
161 mciSetDriverData(dwDevID
, 0);
162 mciFreeCommandResource(wma
->wCommandTable
);
163 HeapFree(GetProcessHeap(), 0, wma
);
166 return (dwDevID
== 0xFFFFFFFF) ? 1 : 0;
169 /**************************************************************************
170 * MCIAVI_drvConfigure [internal]
172 static DWORD
MCIAVI_drvConfigure(DWORD dwDevID
)
174 WINE_MCIAVI
* wma
= (WINE_MCIAVI
*)mciGetDriverData(dwDevID
);
177 MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK
);
183 /**************************************************************************
184 * MCIAVI_mciGetOpenDev [internal]
186 WINE_MCIAVI
* MCIAVI_mciGetOpenDev(UINT wDevID
)
188 WINE_MCIAVI
* wma
= (WINE_MCIAVI
*)mciGetDriverData(wDevID
);
190 if (wma
== NULL
|| wma
->nUseCount
== 0) {
191 WARN("Invalid wDevID=%u\n", wDevID
);
197 static void MCIAVI_CleanUp(WINE_MCIAVI
* wma
)
199 /* to prevent handling in WindowProc */
200 wma
->dwStatus
= MCI_MODE_NOT_READY
;
202 mmioClose(wma
->hFile
, 0);
204 if (wma
->lpVideoIndex
) HeapFree(GetProcessHeap(), 0, wma
->lpVideoIndex
);
205 wma
->lpVideoIndex
= NULL
;
206 if (wma
->lpAudioIndex
) HeapFree(GetProcessHeap(), 0, wma
->lpAudioIndex
);
207 wma
->lpAudioIndex
= NULL
;
208 if (wma
->hic
) ICClose(wma
->hic
);
210 if (wma
->inbih
) HeapFree(GetProcessHeap(), 0, wma
->inbih
);
212 if (wma
->outbih
) HeapFree(GetProcessHeap(), 0, wma
->outbih
);
214 if (wma
->indata
) HeapFree(GetProcessHeap(), 0, wma
->indata
);
216 if (wma
->outdata
) HeapFree(GetProcessHeap(), 0, wma
->outdata
);
218 if (wma
->hbmFrame
) DeleteObject(wma
->hbmFrame
);
220 if (wma
->hWnd
) DestroyWindow(wma
->hWnd
);
223 if (wma
->lpWaveFormat
) HeapFree(GetProcessHeap(), 0, wma
->lpWaveFormat
);
224 wma
->lpWaveFormat
= 0;
226 memset(&wma
->mah
, 0, sizeof(wma
->mah
));
227 memset(&wma
->ash_video
, 0, sizeof(wma
->ash_video
));
228 memset(&wma
->ash_audio
, 0, sizeof(wma
->ash_audio
));
229 wma
->dwCurrVideoFrame
= wma
->dwCurrAudioBlock
= 0;
233 static DWORD
MCIAVI_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
235 /***************************************************************************
236 * MCIAVI_mciOpen [internal]
238 static DWORD
MCIAVI_mciOpen(UINT wDevID
, DWORD dwFlags
,
239 LPMCI_DGV_OPEN_PARMSA lpOpenParms
)
241 WINE_MCIAVI
* wma
= (WINE_MCIAVI
*)mciGetDriverData(wDevID
);
244 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwFlags
, lpOpenParms
);
246 if (lpOpenParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
247 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
249 if (wma
->nUseCount
> 0) {
250 /* The driver is already open on this channel */
251 /* If the driver was opened shareable before and this open specifies */
252 /* shareable then increment the use count */
253 if (wma
->fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
256 return MCIERR_MUST_USE_SHAREABLE
;
259 wma
->fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
262 wma
->dwStatus
= MCI_MODE_NOT_READY
;
263 InitializeCriticalSection(&wma
->cs
);
265 if (dwFlags
& MCI_OPEN_ELEMENT
) {
266 if (dwFlags
& MCI_OPEN_ELEMENT_ID
) {
267 /* could it be that (DWORD)lpOpenParms->lpstrElementName
268 * contains the hFile value ?
270 dwRet
= MCIERR_UNRECOGNIZED_COMMAND
;
271 } else if (strlen(lpOpenParms
->lpstrElementName
) > 0) {
272 /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
273 TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms
->lpstrElementName
);
275 if (lpOpenParms
->lpstrElementName
&& (strlen(lpOpenParms
->lpstrElementName
) > 0)) {
276 wma
->hFile
= mmioOpenA(lpOpenParms
->lpstrElementName
, NULL
,
277 MMIO_ALLOCBUF
| MMIO_DENYWRITE
| MMIO_READWRITE
);
279 if (wma
->hFile
== 0) {
280 WARN("can't find file='%s' !\n", lpOpenParms
->lpstrElementName
);
281 dwRet
= MCIERR_FILE_NOT_FOUND
;
283 if (!MCIAVI_GetInfo(wma
))
284 dwRet
= MCIERR_INVALID_FILE
;
285 else if (!MCIAVI_OpenVideo(wma
))
286 dwRet
= MCIERR_CANNOT_LOAD_DRIVER
;
287 else if (!MCIAVI_CreateWindow(wma
, dwFlags
, lpOpenParms
))
288 dwRet
= MCIERR_CREATEWINDOW
;
292 FIXME("Don't record yet\n");
293 dwRet
= MCIERR_UNSUPPORTED_FUNCTION
;
297 memcpy(&wma
->openParms
, lpOpenParms
, sizeof(MCI_WAVE_OPEN_PARMSA
));
300 wma
->dwStatus
= MCI_MODE_STOP
;
301 wma
->dwMciTimeFormat
= MCI_FORMAT_FRAMES
;
309 /***************************************************************************
310 * MCIAVI_mciClose [internal]
312 static DWORD
MCIAVI_mciClose(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
314 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
317 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwFlags
, lpParms
);
319 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
321 if (wma
->nUseCount
== 1) {
322 if (wma
->dwStatus
!= MCI_MODE_STOP
)
323 dwRet
= MCIAVI_mciStop(wDevID
, MCI_WAIT
, lpParms
);
326 if ((dwFlags
& MCI_NOTIFY
) && lpParms
) {
327 mciDriverNotify(HWND_32(LOWORD(lpParms
->dwCallback
)),
328 wma
->openParms
.wDeviceID
,
329 MCI_NOTIFY_SUCCESSFUL
);
331 HeapFree(GetProcessHeap(), 0, wma
);
338 /***************************************************************************
339 * MCIAVI_mciPlay [internal]
341 static DWORD
MCIAVI_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
343 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
348 LPWAVEHDR waveHdr
= NULL
;
349 unsigned i
, nHdr
= 0;
350 DWORD dwFromFrame
, dwToFrame
;
352 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwFlags
, lpParms
);
354 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
355 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
357 if (!wma
->hFile
) return MCIERR_FILE_NOT_FOUND
;
358 if (!wma
->hWnd
) return MCIERR_NO_WINDOW
;
360 wma
->dwStatus
= MCI_MODE_PLAY
;
362 if (!(dwFlags
& MCI_WAIT
)) {
363 return MCI_SendCommandAsync(wma
->openParms
.wDeviceID
, MCI_PLAY
, dwFlags
,
364 (DWORD
)lpParms
, sizeof(MCI_PLAY_PARMS
));
367 ShowWindow(wma
->hWnd
, SW_SHOW
);
369 dwFromFrame
= wma
->dwCurrVideoFrame
;
370 dwToFrame
= wma
->dwPlayableVideoFrames
- 1;
372 if (lpParms
&& (dwFlags
& MCI_FROM
)) {
373 dwFromFrame
= MCIAVI_ConvertTimeFormatToFrame(wma
, lpParms
->dwFrom
);
375 if (lpParms
&& (dwFlags
& MCI_TO
)) {
376 dwToFrame
= MCIAVI_ConvertTimeFormatToFrame(wma
, lpParms
->dwTo
);
378 if (dwToFrame
>= wma
->dwPlayableVideoFrames
)
379 dwToFrame
= wma
->dwPlayableVideoFrames
- 1;
381 TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame
, dwToFrame
);
383 if (dwToFrame
<= wma
->dwCurrVideoFrame
)
385 wma
->dwCurrVideoFrame
= dwFromFrame
;
387 if (dwFlags
& (MCI_DGV_PLAY_REPEAT
|MCI_DGV_PLAY_REVERSE
|MCI_MCIAVI_PLAY_WINDOW
|MCI_MCIAVI_PLAY_FULLSCREEN
))
388 FIXME("Unsupported flag %08lx\n", dwFlags
);
390 /* time is in microseconds, we should convert it to milliseconds */
391 frameTime
= (wma
->mah
.dwMicroSecPerFrame
+ 500) / 1000;
393 if (wma
->lpWaveFormat
) {
394 if ((dwRet
= MCIAVI_OpenAudio(wma
, &nHdr
, &waveHdr
)) != 0)
396 /* fill the queue with as many wave headers as possible */
397 MCIAVI_PlayAudioBlocks(wma
, nHdr
, waveHdr
);
400 while (wma
->dwStatus
!= MCI_MODE_STOP
&& wma
->dwStatus
!= MCI_MODE_NOT_READY
) {
403 MCIAVI_DrawFrame(wma
);
405 if (wma
->lpWaveFormat
) {
406 MCIAVI_PlayAudioBlocks(wma
, nHdr
, waveHdr
);
407 delta
= GetTickCount() - tc
;
408 WaitForSingleObject(wma
->hEvent
, (delta
>= frameTime
) ? 0 : frameTime
- delta
);
411 delta
= GetTickCount() - tc
;
412 if (delta
< frameTime
)
413 Sleep(frameTime
- delta
);
415 if (wma
->dwCurrVideoFrame
++ >= dwToFrame
) {
416 wma
->dwCurrVideoFrame
--;
417 wma
->dwStatus
= MCI_MODE_STOP
;
421 if (wma
->lpWaveFormat
) {
422 while (*(volatile DWORD
*)&wma
->dwEventCount
!= nHdr
- 1) {
426 /* just to get rid of some race conditions between play, stop and pause */
427 waveOutReset(wma
->hWave
);
429 for (i
= 0; i
< nHdr
; i
++)
430 waveOutUnprepareHeader(wma
->hWave
, &waveHdr
[i
], sizeof(WAVEHDR
));
435 if (wma
->lpWaveFormat
) {
436 HeapFree(GetProcessHeap(), 0, waveHdr
);
439 waveOutClose(wma
->hWave
);
442 CloseHandle(wma
->hEvent
);
445 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
446 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
447 mciDriverNotify(HWND_32(LOWORD(lpParms
->dwCallback
)),
448 wma
->openParms
.wDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
451 wma
->dwStatus
= MCI_MODE_STOP
;
456 /***************************************************************************
457 * MCIAVI_mciRecord [internal]
459 static DWORD
MCIAVI_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_RECORD_PARMS lpParms
)
461 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
463 FIXME("(%04x, %08lX, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
465 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
466 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
468 wma
->dwStatus
= MCI_MODE_RECORD
;
472 /***************************************************************************
473 * MCIAVI_mciStop [internal]
475 static DWORD
MCIAVI_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
477 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
480 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwFlags
, lpParms
);
482 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
483 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
485 switch (wma
->dwStatus
) {
488 case MCI_MODE_RECORD
:
490 int oldStat
= wma
->dwStatus
;
491 wma
->dwStatus
= MCI_MODE_NOT_READY
;
492 if (oldStat
== MCI_MODE_PAUSE
)
493 dwRet
= waveOutReset(wma
->hWave
);
495 while (wma
->dwStatus
!= MCI_MODE_STOP
)
499 wma
->dwStatus
= MCI_MODE_STOP
;
503 if ((dwFlags
& MCI_NOTIFY
) && lpParms
) {
504 mciDriverNotify(HWND_32(LOWORD(lpParms
->dwCallback
)),
505 wma
->openParms
.wDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
511 /***************************************************************************
512 * MCIAVI_mciPause [internal]
514 static DWORD
MCIAVI_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
516 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
518 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
519 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
521 if (wma
->dwStatus
== MCI_MODE_PLAY
)
522 wma
->dwStatus
= MCI_MODE_PAUSE
;
524 return (wma
->lpWaveFormat
) ? waveOutPause(wma
->hWave
) : 0;
527 /***************************************************************************
528 * MCIAVI_mciResume [internal]
530 static DWORD
MCIAVI_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
532 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
534 FIXME("(%04x, %08lX, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
536 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
537 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
539 if (wma
->dwStatus
== MCI_MODE_PAUSE
)
540 wma
->dwStatus
= MCI_MODE_PLAY
;
542 return (wma
->lpWaveFormat
) ? waveOutRestart(wma
->hWave
) : 0;
545 /***************************************************************************
546 * MCIAVI_mciSeek [internal]
548 static DWORD
MCIAVI_mciSeek(UINT wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
)
550 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
552 TRACE("(%04x, %08lX, %p)\n", wDevID
, dwFlags
, lpParms
);
554 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
555 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
557 EnterCriticalSection(&wma
->cs
);
559 MCIAVI_mciStop(wDevID
, MCI_WAIT
, 0);
561 if (dwFlags
& MCI_SEEK_TO_START
) {
562 wma
->dwCurrVideoFrame
= 0;
563 } else if (dwFlags
& MCI_SEEK_TO_END
) {
564 wma
->dwCurrVideoFrame
= wma
->dwPlayableVideoFrames
- 1;
565 } else if (dwFlags
& MCI_TO
) {
566 wma
->dwCurrVideoFrame
= MCIAVI_ConvertTimeFormatToFrame(wma
, lpParms
->dwTo
);
568 WARN("dwFlag doesn't tell where to seek to...\n");
569 return MCIERR_MISSING_PARAMETER
;
572 TRACE("Seeking to frame=%lu bytes\n", wma
->dwCurrVideoFrame
);
574 if (dwFlags
& MCI_NOTIFY
) {
575 mciDriverNotify(HWND_32(LOWORD(lpParms
->dwCallback
)),
576 wma
->openParms
.wDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
579 LeaveCriticalSection(&wma
->cs
);
584 /*****************************************************************************
585 * MCIAVI_mciLoad [internal]
587 static DWORD
MCIAVI_mciLoad(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_LOAD_PARMSA lpParms
)
589 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
591 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
593 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
594 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
599 /******************************************************************************
600 * MCIAVI_mciSave [internal]
602 static DWORD
MCIAVI_mciSave(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_SAVE_PARMSA lpParms
)
604 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
606 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
608 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
609 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
614 /******************************************************************************
615 * MCIAVI_mciFreeze [internal]
617 static DWORD
MCIAVI_mciFreeze(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_RECT_PARMS lpParms
)
619 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
621 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
623 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
624 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
629 /******************************************************************************
630 * MCIAVI_mciRealize [internal]
632 static DWORD
MCIAVI_mciRealize(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
634 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
636 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
638 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
639 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
644 /******************************************************************************
645 * MCIAVI_mciUnFreeze [internal]
647 static DWORD
MCIAVI_mciUnFreeze(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_RECT_PARMS lpParms
)
649 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
651 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
653 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
654 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
659 /******************************************************************************
660 * MCIAVI_mciUpdate [internal]
662 static DWORD
MCIAVI_mciUpdate(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_UPDATE_PARMS lpParms
)
664 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
666 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
668 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
669 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
674 /******************************************************************************
675 * MCIAVI_mciStep [internal]
677 static DWORD
MCIAVI_mciStep(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_STEP_PARMS lpParms
)
679 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
681 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
683 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
684 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
689 /******************************************************************************
690 * MCIAVI_mciCopy [internal]
692 static DWORD
MCIAVI_mciCopy(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_COPY_PARMS lpParms
)
694 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
696 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
698 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
699 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
704 /******************************************************************************
705 * MCIAVI_mciCut [internal]
707 static DWORD
MCIAVI_mciCut(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_CUT_PARMS lpParms
)
709 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
711 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
713 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
714 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
719 /******************************************************************************
720 * MCIAVI_mciDelete [internal]
722 static DWORD
MCIAVI_mciDelete(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_DELETE_PARMS lpParms
)
724 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
726 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
728 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
729 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
734 /******************************************************************************
735 * MCIAVI_mciPaste [internal]
737 static DWORD
MCIAVI_mciPaste(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_PASTE_PARMS lpParms
)
739 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
741 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
743 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
744 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
749 /******************************************************************************
750 * MCIAVI_mciCue [internal]
752 static DWORD
MCIAVI_mciCue(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_CUE_PARMS lpParms
)
754 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
756 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
758 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
759 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
764 /******************************************************************************
765 * MCIAVI_mciCapture [internal]
767 static DWORD
MCIAVI_mciCapture(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_CAPTURE_PARMSA lpParms
)
769 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
771 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
773 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
774 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
779 /******************************************************************************
780 * MCIAVI_mciMonitor [internal]
782 static DWORD
MCIAVI_mciMonitor(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_MONITOR_PARMS lpParms
)
784 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
786 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
788 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
789 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
794 /******************************************************************************
795 * MCIAVI_mciReserve [internal]
797 static DWORD
MCIAVI_mciReserve(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_RESERVE_PARMSA lpParms
)
799 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
801 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
803 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
804 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
809 /******************************************************************************
810 * MCIAVI_mciSetAudio [internal]
812 static DWORD
MCIAVI_mciSetAudio(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_SETAUDIO_PARMSA lpParms
)
814 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
816 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
818 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
819 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
824 /******************************************************************************
825 * MCIAVI_mciSignal [internal]
827 static DWORD
MCIAVI_mciSignal(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_SIGNAL_PARMS lpParms
)
829 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
831 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
833 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
834 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
839 /******************************************************************************
840 * MCIAVI_mciSetVideo [internal]
842 static DWORD
MCIAVI_mciSetVideo(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_SETVIDEO_PARMSA lpParms
)
844 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
846 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
848 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
849 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
854 /******************************************************************************
855 * MCIAVI_mciQuality [internal]
857 static DWORD
MCIAVI_mciQuality(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_QUALITY_PARMSA lpParms
)
859 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
861 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
863 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
864 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
869 /******************************************************************************
870 * MCIAVI_mciList [internal]
872 static DWORD
MCIAVI_mciList(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_LIST_PARMSA lpParms
)
874 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
876 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
878 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
879 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
884 /******************************************************************************
885 * MCIAVI_mciUndo [internal]
887 static DWORD
MCIAVI_mciUndo(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
889 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
891 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
893 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
894 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
899 /******************************************************************************
900 * MCIAVI_mciConfigure [internal]
902 static DWORD
MCIAVI_mciConfigure(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
904 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
906 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
908 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
909 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
914 /******************************************************************************
915 * MCIAVI_mciRestore [internal]
917 static DWORD
MCIAVI_mciRestore(UINT wDevID
, DWORD dwFlags
, LPMCI_DGV_RESTORE_PARMSA lpParms
)
919 WINE_MCIAVI
* wma
= MCIAVI_mciGetOpenDev(wDevID
);
921 FIXME("(%04x, %08lx, %p) : stub\n", wDevID
, dwFlags
, lpParms
);
923 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
924 if (wma
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
929 /*======================================================================*
930 * MCI AVI entry points *
931 *======================================================================*/
933 /**************************************************************************
934 * DriverProc (MCIAVI.@)
936 LONG CALLBACK
MCIAVI_DriverProc(DWORD dwDevID
, HDRVR hDriv
, DWORD wMsg
,
937 DWORD dwParam1
, DWORD dwParam2
)
939 TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",
940 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
943 case DRV_LOAD
: return 1;
944 case DRV_FREE
: return 1;
945 case DRV_OPEN
: return MCIAVI_drvOpen((LPSTR
)dwParam1
, (LPMCI_OPEN_DRIVER_PARMSA
)dwParam2
);
946 case DRV_CLOSE
: return MCIAVI_drvClose(dwDevID
);
947 case DRV_ENABLE
: return 1;
948 case DRV_DISABLE
: return 1;
949 case DRV_QUERYCONFIGURE
: return 1;
950 case DRV_CONFIGURE
: return MCIAVI_drvConfigure(dwDevID
);
951 case DRV_INSTALL
: return DRVCNF_RESTART
;
952 case DRV_REMOVE
: return DRVCNF_RESTART
;
955 if (dwDevID
== 0xFFFFFFFF) return MCIERR_UNSUPPORTED_FUNCTION
;
958 case MCI_OPEN_DRIVER
: return MCIAVI_mciOpen (dwDevID
, dwParam1
, (LPMCI_DGV_OPEN_PARMSA
) dwParam2
);
959 case MCI_CLOSE_DRIVER
: return MCIAVI_mciClose (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
960 case MCI_PLAY
: return MCIAVI_mciPlay (dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
) dwParam2
);
961 case MCI_RECORD
: return MCIAVI_mciRecord (dwDevID
, dwParam1
, (LPMCI_DGV_RECORD_PARMS
) dwParam2
);
962 case MCI_STOP
: return MCIAVI_mciStop (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
963 case MCI_SET
: return MCIAVI_mciSet (dwDevID
, dwParam1
, (LPMCI_DGV_SET_PARMS
) dwParam2
);
964 case MCI_PAUSE
: return MCIAVI_mciPause (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
965 case MCI_RESUME
: return MCIAVI_mciResume (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
966 case MCI_STATUS
: return MCIAVI_mciStatus (dwDevID
, dwParam1
, (LPMCI_DGV_STATUS_PARMSA
) dwParam2
);
967 case MCI_GETDEVCAPS
: return MCIAVI_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
) dwParam2
);
968 case MCI_INFO
: return MCIAVI_mciInfo (dwDevID
, dwParam1
, (LPMCI_DGV_INFO_PARMSA
) dwParam2
);
969 case MCI_SEEK
: return MCIAVI_mciSeek (dwDevID
, dwParam1
, (LPMCI_SEEK_PARMS
) dwParam2
);
970 case MCI_PUT
: return MCIAVI_mciPut (dwDevID
, dwParam1
, (LPMCI_DGV_PUT_PARMS
) dwParam2
);
971 case MCI_WINDOW
: return MCIAVI_mciWindow (dwDevID
, dwParam1
, (LPMCI_DGV_WINDOW_PARMSA
) dwParam2
);
972 case MCI_LOAD
: return MCIAVI_mciLoad (dwDevID
, dwParam1
, (LPMCI_DGV_LOAD_PARMSA
) dwParam2
);
973 case MCI_SAVE
: return MCIAVI_mciSave (dwDevID
, dwParam1
, (LPMCI_DGV_SAVE_PARMSA
) dwParam2
);
974 case MCI_FREEZE
: return MCIAVI_mciFreeze (dwDevID
, dwParam1
, (LPMCI_DGV_RECT_PARMS
) dwParam2
);
975 case MCI_REALIZE
: return MCIAVI_mciRealize (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
976 case MCI_UNFREEZE
: return MCIAVI_mciUnFreeze (dwDevID
, dwParam1
, (LPMCI_DGV_RECT_PARMS
) dwParam2
);
977 case MCI_UPDATE
: return MCIAVI_mciUpdate (dwDevID
, dwParam1
, (LPMCI_DGV_UPDATE_PARMS
) dwParam2
);
978 case MCI_WHERE
: return MCIAVI_mciWhere (dwDevID
, dwParam1
, (LPMCI_DGV_RECT_PARMS
) dwParam2
);
979 case MCI_STEP
: return MCIAVI_mciStep (dwDevID
, dwParam1
, (LPMCI_DGV_STEP_PARMS
) dwParam2
);
980 case MCI_COPY
: return MCIAVI_mciCopy (dwDevID
, dwParam1
, (LPMCI_DGV_COPY_PARMS
) dwParam2
);
981 case MCI_CUT
: return MCIAVI_mciCut (dwDevID
, dwParam1
, (LPMCI_DGV_CUT_PARMS
) dwParam2
);
982 case MCI_DELETE
: return MCIAVI_mciDelete (dwDevID
, dwParam1
, (LPMCI_DGV_DELETE_PARMS
) dwParam2
);
983 case MCI_PASTE
: return MCIAVI_mciPaste (dwDevID
, dwParam1
, (LPMCI_DGV_PASTE_PARMS
) dwParam2
);
984 case MCI_CUE
: return MCIAVI_mciCue (dwDevID
, dwParam1
, (LPMCI_DGV_CUE_PARMS
) dwParam2
);
985 /* Digital Video specific */
986 case MCI_CAPTURE
: return MCIAVI_mciCapture (dwDevID
, dwParam1
, (LPMCI_DGV_CAPTURE_PARMSA
) dwParam2
);
987 case MCI_MONITOR
: return MCIAVI_mciMonitor (dwDevID
, dwParam1
, (LPMCI_DGV_MONITOR_PARMS
) dwParam2
);
988 case MCI_RESERVE
: return MCIAVI_mciReserve (dwDevID
, dwParam1
, (LPMCI_DGV_RESERVE_PARMSA
) dwParam2
);
989 case MCI_SETAUDIO
: return MCIAVI_mciSetAudio (dwDevID
, dwParam1
, (LPMCI_DGV_SETAUDIO_PARMSA
) dwParam2
);
990 case MCI_SIGNAL
: return MCIAVI_mciSignal (dwDevID
, dwParam1
, (LPMCI_DGV_SIGNAL_PARMS
) dwParam2
);
991 case MCI_SETVIDEO
: return MCIAVI_mciSetVideo (dwDevID
, dwParam1
, (LPMCI_DGV_SETVIDEO_PARMSA
) dwParam2
);
992 case MCI_QUALITY
: return MCIAVI_mciQuality (dwDevID
, dwParam1
, (LPMCI_DGV_QUALITY_PARMSA
) dwParam2
);
993 case MCI_LIST
: return MCIAVI_mciList (dwDevID
, dwParam1
, (LPMCI_DGV_LIST_PARMSA
) dwParam2
);
994 case MCI_UNDO
: return MCIAVI_mciUndo (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
995 case MCI_CONFIGURE
: return MCIAVI_mciConfigure (dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
) dwParam2
);
996 case MCI_RESTORE
: return MCIAVI_mciRestore (dwDevID
, dwParam1
, (LPMCI_DGV_RESTORE_PARMSA
) dwParam2
);
1000 WARN("Unsupported command [%lu]\n", wMsg
);
1004 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1007 TRACE("Sending msg [%lu] to default driver proc\n", wMsg
);
1008 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1010 return MCIERR_UNRECOGNIZED_COMMAND
;