xref: /reactos/dll/win32/mciavi32/mciavi.c (revision 9ac5b9a0)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Digital video MCI Wine Driver
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 1999, 2000 Eric POUECH
5c2c66affSColin Finck  * Copyright 2003 Dmitry Timoshkov
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck  * License as published by the Free Software Foundation; either
10c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c2c66affSColin Finck  * Lesser General Public License for more details.
16c2c66affSColin Finck  *
17c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck  */
21c2c66affSColin Finck 
22c2c66affSColin Finck /* TODO list :
23c2c66affSColin Finck  *	- handling of palettes
24c2c66affSColin Finck  *	- recording (which input devices ?), a cam recorder ?
25c2c66affSColin Finck  *	- lots of messages still need to be handled (cf FIXME)
26c2c66affSColin Finck  *	- synchronization between audio and video (especially for interleaved
27c2c66affSColin Finck  *	  files)
28c2c66affSColin Finck  *	- robustness when reading file can be enhanced
29c2c66affSColin Finck  *	- reimplement the AVI handling part with avifile DLL because
30c2c66affSColin Finck  *	  "open @1122334 type avivideo alias a" expects an AVIFile/Stream
31c2c66affSColin Finck  *	  and MCI_DGV_SET|STATUS_SPEED maps to Rate/Scale
32c2c66affSColin Finck  *	- some files appear to have more than one audio stream (we only play the
33c2c66affSColin Finck  *	  first one)
34c2c66affSColin Finck  *	- some files contain an index of audio/video frame. Better use it,
35c2c66affSColin Finck  *	  instead of rebuilding it (AVIFile does that already)
36c2c66affSColin Finck  *	- stopping while playing a file with sound blocks until all buffered
37c2c66affSColin Finck  *        audio is played... still should be stopped ASAP
38c2c66affSColin Finck  */
39c2c66affSColin Finck 
40ba65d708SAmine Khaldi #include <string.h>
41c2c66affSColin Finck #include "private_mciavi.h"
42ba65d708SAmine Khaldi #include "wine/debug.h"
43c2c66affSColin Finck 
44ba65d708SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
45c2c66affSColin Finck 
46c2c66affSColin Finck static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
47c2c66affSColin Finck 
48c2c66affSColin Finck /*======================================================================*
49c2c66affSColin Finck  *                  	    MCI AVI implementation			*
50c2c66affSColin Finck  *======================================================================*/
51c2c66affSColin Finck 
52c2c66affSColin Finck HINSTANCE MCIAVI_hInstance = 0;
53c2c66affSColin Finck 
54c2c66affSColin Finck /***********************************************************************
55c2c66affSColin Finck  *		DllMain (MCIAVI.0)
56c2c66affSColin Finck  */
DllMain(HINSTANCE hInstDLL,DWORD fdwReason,LPVOID fImpLoad)57c2c66affSColin Finck BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
58c2c66affSColin Finck {
59c2c66affSColin Finck     switch (fdwReason) {
60c2c66affSColin Finck     case DLL_PROCESS_ATTACH:
61c2c66affSColin Finck         DisableThreadLibraryCalls(hInstDLL);
62c2c66affSColin Finck 	MCIAVI_hInstance = hInstDLL;
63c2c66affSColin Finck 	break;
64c2c66affSColin Finck     }
65c2c66affSColin Finck     return TRUE;
66c2c66affSColin Finck }
67c2c66affSColin Finck 
68c2c66affSColin Finck /**************************************************************************
69c2c66affSColin Finck  * 				MCIAVI_drvOpen			[internal]
70c2c66affSColin Finck  */
MCIAVI_drvOpen(LPCWSTR str,LPMCI_OPEN_DRIVER_PARMSW modp)71c2c66affSColin Finck static	DWORD	MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
72c2c66affSColin Finck {
73c2c66affSColin Finck     WINE_MCIAVI*	wma;
74c2c66affSColin Finck     static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
75c2c66affSColin Finck 
76c2c66affSColin Finck     TRACE("%s, %p\n", debugstr_w(str), modp);
77c2c66affSColin Finck 
78c2c66affSColin Finck     /* session instance */
79c2c66affSColin Finck     if (!modp) return 0xFFFFFFFF;
80c2c66affSColin Finck 
81c2c66affSColin Finck     if (!MCIAVI_RegisterClass()) return 0;
82c2c66affSColin Finck 
83c2c66affSColin Finck     wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
84c2c66affSColin Finck     if (!wma)
85c2c66affSColin Finck 	return 0;
86c2c66affSColin Finck 
87c2c66affSColin Finck     InitializeCriticalSection(&wma->cs);
88c2c66affSColin Finck     wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs");
89c2c66affSColin Finck     wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
90c2c66affSColin Finck     wma->wDevID = modp->wDeviceID;
91c2c66affSColin Finck     wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
92c2c66affSColin Finck     wma->dwStatus = MCI_MODE_NOT_READY;
93c2c66affSColin Finck     modp->wCustomCommandTable = wma->wCommandTable;
94c2c66affSColin Finck     modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
95c2c66affSColin Finck     mciSetDriverData(wma->wDevID, (DWORD_PTR)wma);
96c2c66affSColin Finck 
97c2c66affSColin Finck     return modp->wDeviceID;
98c2c66affSColin Finck }
99c2c66affSColin Finck 
100c2c66affSColin Finck /**************************************************************************
101c2c66affSColin Finck  * 				MCIAVI_drvClose		[internal]
102c2c66affSColin Finck  */
MCIAVI_drvClose(DWORD dwDevID)103c2c66affSColin Finck static	DWORD	MCIAVI_drvClose(DWORD dwDevID)
104c2c66affSColin Finck {
105c2c66affSColin Finck     WINE_MCIAVI *wma;
106c2c66affSColin Finck 
107c2c66affSColin Finck     TRACE("%04x\n", dwDevID);
108c2c66affSColin Finck 
109c2c66affSColin Finck     /* finish all outstanding things */
110c2c66affSColin Finck     MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL);
111c2c66affSColin Finck 
112c2c66affSColin Finck     wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
113c2c66affSColin Finck 
114c2c66affSColin Finck     if (wma) {
115c2c66affSColin Finck         MCIAVI_UnregisterClass();
116c2c66affSColin Finck 
117c2c66affSColin Finck         EnterCriticalSection(&wma->cs);
118c2c66affSColin Finck 
119c2c66affSColin Finck 	mciSetDriverData(dwDevID, 0);
120c2c66affSColin Finck 	mciFreeCommandResource(wma->wCommandTable);
121c2c66affSColin Finck 
122c2c66affSColin Finck         CloseHandle(wma->hStopEvent);
123c2c66affSColin Finck 
124c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
125c2c66affSColin Finck         wma->cs.DebugInfo->Spare[0] = 0;
126c2c66affSColin Finck         DeleteCriticalSection(&wma->cs);
127c2c66affSColin Finck 
128c2c66affSColin Finck 	HeapFree(GetProcessHeap(), 0, wma);
129c2c66affSColin Finck 	return 1;
130c2c66affSColin Finck     }
131c2c66affSColin Finck     return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
132c2c66affSColin Finck }
133c2c66affSColin Finck 
134c2c66affSColin Finck /**************************************************************************
135c2c66affSColin Finck  * 				MCIAVI_drvConfigure		[internal]
136c2c66affSColin Finck  */
MCIAVI_drvConfigure(DWORD dwDevID)137c2c66affSColin Finck static	DWORD	MCIAVI_drvConfigure(DWORD dwDevID)
138c2c66affSColin Finck {
139c2c66affSColin Finck     WINE_MCIAVI *wma;
140c2c66affSColin Finck 
141c2c66affSColin Finck     TRACE("%04x\n", dwDevID);
142c2c66affSColin Finck 
143c2c66affSColin Finck     MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);
144c2c66affSColin Finck 
145c2c66affSColin Finck     wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
146c2c66affSColin Finck 
147c2c66affSColin Finck     if (wma) {
148c2c66affSColin Finck 	MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
149c2c66affSColin Finck 	return 1;
150c2c66affSColin Finck     }
151c2c66affSColin Finck     return 0;
152c2c66affSColin Finck }
153c2c66affSColin Finck 
154c2c66affSColin Finck /**************************************************************************
155c2c66affSColin Finck  * 				MCIAVI_mciGetOpenDev		[internal]
156c2c66affSColin Finck  */
MCIAVI_mciGetOpenDev(UINT wDevID)157c2c66affSColin Finck WINE_MCIAVI*  MCIAVI_mciGetOpenDev(UINT wDevID)
158c2c66affSColin Finck {
159c2c66affSColin Finck     WINE_MCIAVI*	wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
160c2c66affSColin Finck 
161c2c66affSColin Finck     if (wma == NULL || wma->nUseCount == 0) {
162c2c66affSColin Finck 	WARN("Invalid wDevID=%u\n", wDevID);
163c2c66affSColin Finck 	return 0;
164c2c66affSColin Finck     }
165c2c66affSColin Finck     return wma;
166c2c66affSColin Finck }
167c2c66affSColin Finck 
MCIAVI_CleanUp(WINE_MCIAVI * wma)168c2c66affSColin Finck static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
169c2c66affSColin Finck {
170c2c66affSColin Finck     /* to prevent handling in WindowProc */
171c2c66affSColin Finck     wma->dwStatus = MCI_MODE_NOT_READY;
172c2c66affSColin Finck     if (wma->hFile) {
173c2c66affSColin Finck 	mmioClose(wma->hFile, 0);
174c2c66affSColin Finck 	wma->hFile = 0;
175c2c66affSColin Finck 
176c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->lpFileName);
177c2c66affSColin Finck         wma->lpFileName = NULL;
178c2c66affSColin Finck 
179c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
180c2c66affSColin Finck 	wma->lpVideoIndex = NULL;
181c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
182c2c66affSColin Finck 	wma->lpAudioIndex = NULL;
183c2c66affSColin Finck 	if (wma->hic)		ICClose(wma->hic);
184c2c66affSColin Finck 	wma->hic = 0;
185c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->inbih);
186c2c66affSColin Finck 	wma->inbih = NULL;
187c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->outbih);
188c2c66affSColin Finck 	wma->outbih = NULL;
189c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->indata);
190c2c66affSColin Finck 	wma->indata = NULL;
191c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->outdata);
192c2c66affSColin Finck 	wma->outdata = NULL;
193c2c66affSColin Finck     	if (wma->hbmFrame)	DeleteObject(wma->hbmFrame);
194c2c66affSColin Finck 	wma->hbmFrame = 0;
195c2c66affSColin Finck 	if (wma->hWnd)		DestroyWindow(wma->hWnd);
196c2c66affSColin Finck 	wma->hWnd = 0;
197c2c66affSColin Finck 
198c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
199c2c66affSColin Finck 	wma->lpWaveFormat = 0;
200c2c66affSColin Finck 
201c2c66affSColin Finck 	memset(&wma->mah, 0, sizeof(wma->mah));
202c2c66affSColin Finck 	memset(&wma->ash_video, 0, sizeof(wma->ash_video));
203c2c66affSColin Finck 	memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
204c2c66affSColin Finck 	wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
205c2c66affSColin Finck         wma->dwCachedFrame = -1;
206c2c66affSColin Finck     }
207c2c66affSColin Finck }
208c2c66affSColin Finck 
209c2c66affSColin Finck /***************************************************************************
210c2c66affSColin Finck  * 				MCIAVI_mciOpen			[internal]
211c2c66affSColin Finck  */
MCIAVI_mciOpen(UINT wDevID,DWORD dwFlags,LPMCI_DGV_OPEN_PARMSW lpOpenParms)212c2c66affSColin Finck static	DWORD	MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
213c2c66affSColin Finck                                LPMCI_DGV_OPEN_PARMSW lpOpenParms)
214c2c66affSColin Finck {
215c2c66affSColin Finck     WINE_MCIAVI *wma;
216c2c66affSColin Finck     LRESULT		dwRet = 0;
217c2c66affSColin Finck 
218c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
219c2c66affSColin Finck 
220c2c66affSColin Finck     if (lpOpenParms == NULL) 		return MCIERR_NULL_PARAMETER_BLOCK;
221c2c66affSColin Finck 
222c2c66affSColin Finck     wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
223c2c66affSColin Finck     if (wma == NULL)			return MCIERR_INVALID_DEVICE_ID;
224c2c66affSColin Finck 
225c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
226c2c66affSColin Finck 
227c2c66affSColin Finck     if (wma->nUseCount > 0) {
228c2c66affSColin Finck 	/* The driver is already open on this channel */
229c2c66affSColin Finck 	/* If the driver was opened shareable before and this open specifies */
230c2c66affSColin Finck 	/* shareable then increment the use count */
231c2c66affSColin Finck 	if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
232c2c66affSColin Finck 	    ++wma->nUseCount;
233c2c66affSColin Finck 	else
234c2c66affSColin Finck         {
235c2c66affSColin Finck             LeaveCriticalSection(&wma->cs);
236c2c66affSColin Finck 	    return MCIERR_MUST_USE_SHAREABLE;
237c2c66affSColin Finck         }
238c2c66affSColin Finck     } else {
239c2c66affSColin Finck 	wma->nUseCount = 1;
240c2c66affSColin Finck 	wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
241c2c66affSColin Finck     }
242c2c66affSColin Finck 
243c2c66affSColin Finck     wma->dwStatus = MCI_MODE_NOT_READY;
244c2c66affSColin Finck 
245c2c66affSColin Finck     if (dwFlags & MCI_OPEN_ELEMENT) {
246c2c66affSColin Finck 	if (dwFlags & MCI_OPEN_ELEMENT_ID) {
247c2c66affSColin Finck 	    /* could it be that (DWORD)lpOpenParms->lpstrElementName
248c2c66affSColin Finck 	     * contains the hFile value ?
249c2c66affSColin Finck 	     */
250c2c66affSColin Finck 	    dwRet = MCIERR_UNRECOGNIZED_COMMAND;
251c2c66affSColin Finck 	} else if (lpOpenParms->lpstrElementName && lpOpenParms->lpstrElementName[0]) {
252c2c66affSColin Finck 	    /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
253c2c66affSColin Finck 	    TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(lpOpenParms->lpstrElementName));
254c2c66affSColin Finck 
255*9ac5b9a0SAmine Khaldi             wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(lpOpenParms->lpstrElementName) + 1) * sizeof(WCHAR));
256*9ac5b9a0SAmine Khaldi             lstrcpyW(wma->lpFileName, lpOpenParms->lpstrElementName);
257c2c66affSColin Finck 
258c2c66affSColin Finck 	    if (lpOpenParms->lpstrElementName[0] == '@') {
259c2c66affSColin Finck 		/* The file name @11223344 encodes an AVIFile handle in decimal notation
260c2c66affSColin Finck 		 * in Win3.1 and w2k/NT, but this feature is absent in win95 (KB140750).
261*9ac5b9a0SAmine Khaldi 		 * wma->hFile = LongToHandle(wcstol(lpOpenParms->lpstrElementName+1, NULL, 10)); */
262c2c66affSColin Finck 		FIXME("Using AVIFile/Stream %s NIY\n", debugstr_w(lpOpenParms->lpstrElementName));
263c2c66affSColin Finck 	    }
264c2c66affSColin Finck 	    wma->hFile = mmioOpenW(lpOpenParms->lpstrElementName, NULL,
265c2c66affSColin Finck 				   MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READ);
266c2c66affSColin Finck 
267c2c66affSColin Finck 	    if (wma->hFile == 0) {
268c2c66affSColin Finck 		WARN("can't find file=%s!\n", debugstr_w(lpOpenParms->lpstrElementName));
269c2c66affSColin Finck 		dwRet = MCIERR_FILE_NOT_FOUND;
270c2c66affSColin Finck 	    } else {
271c2c66affSColin Finck 		if (!MCIAVI_GetInfo(wma))
272c2c66affSColin Finck 		    dwRet = MCIERR_INVALID_FILE;
273c2c66affSColin Finck 		else if (!MCIAVI_OpenVideo(wma))
274c2c66affSColin Finck 		    dwRet = MCIERR_CANNOT_LOAD_DRIVER;
275c2c66affSColin Finck 		else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
276c2c66affSColin Finck 		    dwRet = MCIERR_CREATEWINDOW;
277c2c66affSColin Finck 	    }
278c2c66affSColin Finck 	} else {
279c2c66affSColin Finck 	    FIXME("Don't record yet\n");
280c2c66affSColin Finck 	    dwRet = MCIERR_UNSUPPORTED_FUNCTION;
281c2c66affSColin Finck 	}
282c2c66affSColin Finck     }
283c2c66affSColin Finck 
284c2c66affSColin Finck     if (dwRet == 0) {
285c2c66affSColin Finck         TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID);
286c2c66affSColin Finck 
287c2c66affSColin Finck 	wma->dwStatus = MCI_MODE_STOP;
288c2c66affSColin Finck 	wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
289c2c66affSColin Finck     } else {
290c2c66affSColin Finck 	MCIAVI_CleanUp(wma);
291c2c66affSColin Finck     }
292c2c66affSColin Finck 
293c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
294c2c66affSColin Finck 
295c2c66affSColin Finck     if (!dwRet && (dwFlags & MCI_NOTIFY)) {
296c2c66affSColin Finck 	mciDriverNotify(HWND_32(LOWORD(lpOpenParms->dwCallback)),
297c2c66affSColin Finck                        wDevID, MCI_NOTIFY_SUCCESSFUL);
298c2c66affSColin Finck     }
299c2c66affSColin Finck     return dwRet;
300c2c66affSColin Finck }
301c2c66affSColin Finck 
302c2c66affSColin Finck /***************************************************************************
303c2c66affSColin Finck  * 				MCIAVI_mciClose			[internal]
304c2c66affSColin Finck  */
MCIAVI_mciClose(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)305c2c66affSColin Finck DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
306c2c66affSColin Finck {
307c2c66affSColin Finck     WINE_MCIAVI *wma;
308c2c66affSColin Finck     DWORD		dwRet = 0;
309c2c66affSColin Finck 
310c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
311c2c66affSColin Finck 
312c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
313c2c66affSColin Finck     if (wma == NULL) 	return MCIERR_INVALID_DEVICE_ID;
314c2c66affSColin Finck 
315c2c66affSColin Finck     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
316c2c66affSColin Finck 
317c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
318c2c66affSColin Finck 
319c2c66affSColin Finck     if (wma->nUseCount == 1) {
320c2c66affSColin Finck     	MCIAVI_CleanUp(wma);
321c2c66affSColin Finck 
322c2c66affSColin Finck 	if ((dwFlags & MCI_NOTIFY) && lpParms) {
323c2c66affSColin Finck 	    mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
324c2c66affSColin Finck                            wDevID,
325c2c66affSColin Finck 			    MCI_NOTIFY_SUCCESSFUL);
326c2c66affSColin Finck 	}
327c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
328c2c66affSColin Finck 	return dwRet;
329c2c66affSColin Finck     }
330c2c66affSColin Finck     wma->nUseCount--;
331c2c66affSColin Finck 
332c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
333c2c66affSColin Finck     return dwRet;
334c2c66affSColin Finck }
335c2c66affSColin Finck 
currenttime_us(void)336c2c66affSColin Finck static double currenttime_us(void)
337c2c66affSColin Finck {
338c2c66affSColin Finck     LARGE_INTEGER lc, lf;
339c2c66affSColin Finck     QueryPerformanceCounter(&lc);
340c2c66affSColin Finck     QueryPerformanceFrequency(&lf);
341c2c66affSColin Finck     return (lc.QuadPart * 1000000) / lf.QuadPart;
342c2c66affSColin Finck }
343c2c66affSColin Finck 
344c2c66affSColin Finck /***************************************************************************
345c2c66affSColin Finck  * 				MCIAVI_player			[internal]
346c2c66affSColin Finck  */
MCIAVI_player(WINE_MCIAVI * wma,DWORD dwFlags,LPMCI_PLAY_PARMS lpParms)347c2c66affSColin Finck static	DWORD	MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
348c2c66affSColin Finck {
349c2c66affSColin Finck     DWORD		dwRet;
350c2c66affSColin Finck     LPWAVEHDR		waveHdr = NULL;
351c2c66affSColin Finck     unsigned		i, nHdr = 0;
352c2c66affSColin Finck     DWORD		numEvents = 1;
353c2c66affSColin Finck     HANDLE		events[2];
354c2c66affSColin Finck     double next_frame_us;
355c2c66affSColin Finck     BOOL wait_audio = TRUE;
356c2c66affSColin Finck 
357c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
358c2c66affSColin Finck 
359c2c66affSColin Finck     if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
360c2c66affSColin Finck     {
361c2c66affSColin Finck         dwRet = 0;
362c2c66affSColin Finck         goto mci_play_done;
363c2c66affSColin Finck     }
364c2c66affSColin Finck 
365c2c66affSColin Finck     events[0] = wma->hStopEvent;
366c2c66affSColin Finck     if (wma->lpWaveFormat) {
367c2c66affSColin Finck        if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
368c2c66affSColin Finck         {
369c2c66affSColin Finck             /* can't play audio */
370c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
371c2c66affSColin Finck             wma->lpWaveFormat = NULL;
372c2c66affSColin Finck         }
373c2c66affSColin Finck        else
374c2c66affSColin Finck        {
375c2c66affSColin Finck             /* fill the queue with as many wave headers as possible */
376c2c66affSColin Finck             MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
377c2c66affSColin Finck             events[1] = wma->hEvent;
378c2c66affSColin Finck             numEvents = 2;
379c2c66affSColin Finck        }
380c2c66affSColin Finck     }
381c2c66affSColin Finck 
382c2c66affSColin Finck     next_frame_us = currenttime_us();
383c2c66affSColin Finck     while (wma->dwStatus == MCI_MODE_PLAY)
384c2c66affSColin Finck     {
385c2c66affSColin Finck         HDC hDC;
386c2c66affSColin Finck         double tc, delta;
387c2c66affSColin Finck         DWORD ret;
388c2c66affSColin Finck 
389c2c66affSColin Finck         tc = currenttime_us();
390c2c66affSColin Finck 
391c2c66affSColin Finck         hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
392c2c66affSColin Finck         if (hDC)
393c2c66affSColin Finck         {
394c2c66affSColin Finck             while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame){
395c2c66affSColin Finck                 double dur;
396c2c66affSColin Finck                 dur = MCIAVI_PaintFrame(wma, hDC);
397c2c66affSColin Finck                 ++wma->dwCurrVideoFrame;
398c2c66affSColin Finck                 if(!dur)
399c2c66affSColin Finck                     break;
400c2c66affSColin Finck                 next_frame_us += dur;
401c2c66affSColin Finck                 TRACE("next_frame: %f\n", next_frame_us);
402c2c66affSColin Finck             }
403c2c66affSColin Finck             ReleaseDC(wma->hWndPaint, hDC);
404c2c66affSColin Finck         }
405c2c66affSColin Finck         if (wma->dwCurrVideoFrame >= wma->dwToVideoFrame)
406c2c66affSColin Finck         {
407c2c66affSColin Finck             if (!(dwFlags & MCI_DGV_PLAY_REPEAT))
408c2c66affSColin Finck                 break;
409c2c66affSColin Finck             TRACE("repeat media as requested\n");
410c2c66affSColin Finck             wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
411c2c66affSColin Finck         }
412c2c66affSColin Finck 
413c2c66affSColin Finck         if (wma->lpWaveFormat)
414c2c66affSColin Finck             MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
415c2c66affSColin Finck 
416c2c66affSColin Finck         tc = currenttime_us();
417c2c66affSColin Finck         if (tc < next_frame_us)
418c2c66affSColin Finck             delta = next_frame_us - tc;
419c2c66affSColin Finck         else
420c2c66affSColin Finck             delta = 0;
421c2c66affSColin Finck 
422c2c66affSColin Finck         /* check if the playback was cancelled */
423c2c66affSColin Finck         if ((wma->mci_break.flags & MCI_BREAK_KEY) &&
424c2c66affSColin Finck             (GetAsyncKeyState(wma->mci_break.parms.nVirtKey) & 0x8000))
425c2c66affSColin Finck         {
426c2c66affSColin Finck             if (!(wma->mci_break.flags & MCI_BREAK_HWND) ||
427c2c66affSColin Finck                 GetForegroundWindow() == wma->mci_break.parms.hwndBreak)
428c2c66affSColin Finck             {
429c2c66affSColin Finck                 /* we queue audio blocks ahead so ignore them otherwise the audio
430c2c66affSColin Finck                  * will keep playing until the buffer is empty */
431c2c66affSColin Finck                 wait_audio = FALSE;
432c2c66affSColin Finck 
433c2c66affSColin Finck                 TRACE("playback cancelled using break key\n");
434c2c66affSColin Finck                 break;
435c2c66affSColin Finck             }
436c2c66affSColin Finck         }
437c2c66affSColin Finck 
438c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
439c2c66affSColin Finck         ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000);
440c2c66affSColin Finck         EnterCriticalSection(&wma->cs);
441c2c66affSColin Finck         if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
442c2c66affSColin Finck     }
443c2c66affSColin Finck 
444c2c66affSColin Finck     if (wma->lpWaveFormat)
445c2c66affSColin Finck     {
446c2c66affSColin Finck         if (wait_audio)
447c2c66affSColin Finck             while (wma->dwEventCount != nHdr - 1)
448c2c66affSColin Finck             {
449c2c66affSColin Finck                 LeaveCriticalSection(&wma->cs);
450c2c66affSColin Finck                 Sleep(100);
451c2c66affSColin Finck                 EnterCriticalSection(&wma->cs);
452c2c66affSColin Finck             }
453c2c66affSColin Finck 
454c2c66affSColin Finck 	/* just to get rid of some race conditions between play, stop and pause */
455c2c66affSColin Finck 	LeaveCriticalSection(&wma->cs);
456c2c66affSColin Finck 	waveOutReset(wma->hWave);
457c2c66affSColin Finck 	EnterCriticalSection(&wma->cs);
458c2c66affSColin Finck 
459c2c66affSColin Finck 	for (i = 0; i < nHdr; i++)
460c2c66affSColin Finck 	    waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
461c2c66affSColin Finck     }
462c2c66affSColin Finck 
463c2c66affSColin Finck     dwRet = 0;
464c2c66affSColin Finck 
465c2c66affSColin Finck     if (wma->lpWaveFormat) {
466c2c66affSColin Finck 	HeapFree(GetProcessHeap(), 0, waveHdr);
467c2c66affSColin Finck 
468c2c66affSColin Finck 	if (wma->hWave) {
469c2c66affSColin Finck 	    LeaveCriticalSection(&wma->cs);
470c2c66affSColin Finck 	    waveOutClose(wma->hWave);
471c2c66affSColin Finck 	    EnterCriticalSection(&wma->cs);
472c2c66affSColin Finck 	    wma->hWave = 0;
473c2c66affSColin Finck 	}
474c2c66affSColin Finck 	CloseHandle(wma->hEvent);
475c2c66affSColin Finck     }
476c2c66affSColin Finck 
477c2c66affSColin Finck mci_play_done:
478c2c66affSColin Finck     wma->dwStatus = MCI_MODE_STOP;
479c2c66affSColin Finck 
480c2c66affSColin Finck     if (dwFlags & MCI_NOTIFY) {
481c2c66affSColin Finck 	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
482c2c66affSColin Finck 	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
483c2c66affSColin Finck                        wma->wDevID, MCI_NOTIFY_SUCCESSFUL);
484c2c66affSColin Finck     }
485c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
486c2c66affSColin Finck     return dwRet;
487c2c66affSColin Finck }
488c2c66affSColin Finck 
489c2c66affSColin Finck struct MCIAVI_play_data
490c2c66affSColin Finck {
491c2c66affSColin Finck     WINE_MCIAVI *wma;
492c2c66affSColin Finck     DWORD flags;
493c2c66affSColin Finck     MCI_PLAY_PARMS params; /* FIXME: notify via wma->hCallback like the other MCI drivers */
494c2c66affSColin Finck };
495c2c66affSColin Finck 
496c2c66affSColin Finck /*
497c2c66affSColin Finck  * MCIAVI_mciPlay_thread
498c2c66affSColin Finck  *
499c2c66affSColin Finck  * FIXME: probably should use a common worker thread created at the driver
500c2c66affSColin Finck  * load time and queue all async commands to it.
501c2c66affSColin Finck  */
MCIAVI_mciPlay_thread(LPVOID arg)502c2c66affSColin Finck static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg)
503c2c66affSColin Finck {
504c2c66affSColin Finck     struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg;
505c2c66affSColin Finck     DWORD ret;
506c2c66affSColin Finck 
507c2c66affSColin Finck     TRACE("In thread before async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags);
508c2c66affSColin Finck     ret = MCIAVI_player(data->wma, data->flags, &data->params);
509c2c66affSColin Finck     TRACE("In thread after async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags);
510c2c66affSColin Finck 
511c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, data);
512c2c66affSColin Finck     return ret;
513c2c66affSColin Finck }
514c2c66affSColin Finck 
515c2c66affSColin Finck /*
516c2c66affSColin Finck  * MCIAVI_mciPlay_async
517c2c66affSColin Finck  */
MCIAVI_mciPlay_async(WINE_MCIAVI * wma,DWORD dwFlags,LPMCI_PLAY_PARMS lpParams)518c2c66affSColin Finck static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams)
519c2c66affSColin Finck {
520c2c66affSColin Finck     HANDLE handle;
521c2c66affSColin Finck     struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data));
522c2c66affSColin Finck 
523c2c66affSColin Finck     if (!data) return MCIERR_OUT_OF_MEMORY;
524c2c66affSColin Finck 
525c2c66affSColin Finck     data->wma = wma;
526c2c66affSColin Finck     data->flags = dwFlags;
527c2c66affSColin Finck     if (dwFlags & MCI_NOTIFY)
528c2c66affSColin Finck         data->params.dwCallback = lpParams->dwCallback;
529c2c66affSColin Finck 
530c2c66affSColin Finck     if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL)))
531c2c66affSColin Finck     {
532c2c66affSColin Finck         WARN("Couldn't create thread for async play, playing synchronously\n");
533c2c66affSColin Finck         return MCIAVI_mciPlay_thread(data);
534c2c66affSColin Finck     }
535c2c66affSColin Finck     SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
536c2c66affSColin Finck     CloseHandle(handle);
537c2c66affSColin Finck     return 0;
538c2c66affSColin Finck }
539c2c66affSColin Finck 
540c2c66affSColin Finck /***************************************************************************
541c2c66affSColin Finck  * 				MCIAVI_mciPlay			[internal]
542c2c66affSColin Finck  */
MCIAVI_mciPlay(UINT wDevID,DWORD dwFlags,LPMCI_PLAY_PARMS lpParms)543c2c66affSColin Finck static	DWORD	MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
544c2c66affSColin Finck {
545c2c66affSColin Finck     WINE_MCIAVI *wma;
546c2c66affSColin Finck     DWORD		dwRet;
547c2c66affSColin Finck     DWORD		dwFromFrame, dwToFrame;
548c2c66affSColin Finck 
549c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
550c2c66affSColin Finck 
551c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
552c2c66affSColin Finck 
553c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
554c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
555c2c66affSColin Finck     if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION;
556c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
557c2c66affSColin Finck 
558*9ac5b9a0SAmine Khaldi     if (dwFlags & (MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLBY2))
559c2c66affSColin Finck 	FIXME("Unsupported flag %08x\n", dwFlags);
560c2c66affSColin Finck 
561c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
562c2c66affSColin Finck 
563c2c66affSColin Finck     if (!wma->hFile)
564c2c66affSColin Finck     {
565c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
566c2c66affSColin Finck         return MCIERR_FILE_NOT_FOUND;
567c2c66affSColin Finck     }
568c2c66affSColin Finck     if (!wma->hWndPaint)
569c2c66affSColin Finck     {
570c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
571c2c66affSColin Finck         return MCIERR_NO_WINDOW;
572c2c66affSColin Finck     }
573c2c66affSColin Finck 
574c2c66affSColin Finck     dwFromFrame = wma->dwCurrVideoFrame;
575c2c66affSColin Finck     dwToFrame = wma->dwPlayableVideoFrames - 1;
576c2c66affSColin Finck 
577c2c66affSColin Finck     if (dwFlags & MCI_FROM) {
578c2c66affSColin Finck 	dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
579c2c66affSColin Finck     }
580c2c66affSColin Finck     if (dwFlags & MCI_TO) {
581c2c66affSColin Finck 	dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
582c2c66affSColin Finck     }
583c2c66affSColin Finck     if (dwToFrame >= wma->dwPlayableVideoFrames)
584c2c66affSColin Finck 	dwToFrame = wma->dwPlayableVideoFrames - 1;
585c2c66affSColin Finck 
586c2c66affSColin Finck     TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame);
587c2c66affSColin Finck 
588c2c66affSColin Finck     wma->dwCurrVideoFrame = dwFromFrame;
589c2c66affSColin Finck     wma->dwToVideoFrame = dwToFrame;
590c2c66affSColin Finck 
591c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
592c2c66affSColin Finck 
593*9ac5b9a0SAmine Khaldi     if (dwFlags & MCI_MCIAVI_PLAY_FULLSCREEN)
594*9ac5b9a0SAmine Khaldi     {
595*9ac5b9a0SAmine Khaldi         HMONITOR mon = MonitorFromWindow(wma->hWndPaint, MONITOR_DEFAULTTONEAREST);
596*9ac5b9a0SAmine Khaldi         MONITORINFO mi;
597*9ac5b9a0SAmine Khaldi         mi.cbSize = sizeof(mi);
598*9ac5b9a0SAmine Khaldi         GetMonitorInfoA(mon, &mi);
599*9ac5b9a0SAmine Khaldi         wma->hWndPaint = CreateWindowA("STATIC", NULL, WS_POPUP | WS_VISIBLE, mi.rcMonitor.left,
600*9ac5b9a0SAmine Khaldi             mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top,
601*9ac5b9a0SAmine Khaldi             NULL, NULL, NULL, 0);
602*9ac5b9a0SAmine Khaldi     }
603*9ac5b9a0SAmine Khaldi     /* if not fullscreen ensure the window is visible */
604*9ac5b9a0SAmine Khaldi     else if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
605c2c66affSColin Finck         ShowWindow(wma->hWndPaint, SW_SHOWNA);
606c2c66affSColin Finck 
607c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
608c2c66affSColin Finck 
609c2c66affSColin Finck     /* if already playing exit */
610c2c66affSColin Finck     if (wma->dwStatus == MCI_MODE_PLAY)
611c2c66affSColin Finck     {
612c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
613c2c66affSColin Finck         return 0;
614c2c66affSColin Finck     }
615c2c66affSColin Finck 
616c2c66affSColin Finck     wma->dwStatus = MCI_MODE_PLAY;
617c2c66affSColin Finck 
618c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
619c2c66affSColin Finck 
620c2c66affSColin Finck     if (dwFlags & MCI_WAIT)
621c2c66affSColin Finck         return MCIAVI_player(wma, dwFlags, lpParms);
622c2c66affSColin Finck 
623c2c66affSColin Finck     dwRet = MCIAVI_mciPlay_async(wma, dwFlags, lpParms);
624c2c66affSColin Finck 
625c2c66affSColin Finck     if (dwRet) {
626c2c66affSColin Finck         EnterCriticalSection(&wma->cs);
627c2c66affSColin Finck         wma->dwStatus = MCI_MODE_STOP;
628c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
629c2c66affSColin Finck     }
630c2c66affSColin Finck     return dwRet;
631c2c66affSColin Finck }
632c2c66affSColin Finck 
633c2c66affSColin Finck /***************************************************************************
634c2c66affSColin Finck  * 				MCIAVI_mciStop			[internal]
635c2c66affSColin Finck  */
MCIAVI_mciStop(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)636c2c66affSColin Finck static	DWORD	MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
637c2c66affSColin Finck {
638c2c66affSColin Finck     WINE_MCIAVI *wma;
639c2c66affSColin Finck     DWORD		dwRet = 0;
640c2c66affSColin Finck 
641c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
642c2c66affSColin Finck 
643c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
644c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
645c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
646c2c66affSColin Finck 
647c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
648c2c66affSColin Finck 
649c2c66affSColin Finck     TRACE("current status %04x\n", wma->dwStatus);
650c2c66affSColin Finck 
651c2c66affSColin Finck     switch (wma->dwStatus) {
652c2c66affSColin Finck     case MCI_MODE_PLAY:
653c2c66affSColin Finck     case MCI_MODE_RECORD:
654c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
655c2c66affSColin Finck         SetEvent(wma->hStopEvent);
656c2c66affSColin Finck         EnterCriticalSection(&wma->cs);
657c2c66affSColin Finck         /* fall through */
658c2c66affSColin Finck     case MCI_MODE_PAUSE:
659c2c66affSColin Finck 	/* Since our wave notification callback takes the lock,
660c2c66affSColin Finck 	 * we must release it before resetting the device */
661c2c66affSColin Finck         LeaveCriticalSection(&wma->cs);
662c2c66affSColin Finck         dwRet = waveOutReset(wma->hWave);
663c2c66affSColin Finck         EnterCriticalSection(&wma->cs);
664c2c66affSColin Finck         /* fall through */
665c2c66affSColin Finck     default:
666c2c66affSColin Finck         do /* one more chance for an async thread to finish */
667c2c66affSColin Finck         {
668c2c66affSColin Finck             LeaveCriticalSection(&wma->cs);
669c2c66affSColin Finck             Sleep(10);
670c2c66affSColin Finck             EnterCriticalSection(&wma->cs);
671c2c66affSColin Finck         } while (wma->dwStatus != MCI_MODE_STOP);
672c2c66affSColin Finck 
673c2c66affSColin Finck 	break;
674c2c66affSColin Finck 
675c2c66affSColin Finck     case MCI_MODE_NOT_READY:
676c2c66affSColin Finck         break;
677c2c66affSColin Finck     }
678c2c66affSColin Finck 
679c2c66affSColin Finck     if ((dwFlags & MCI_NOTIFY) && lpParms) {
680c2c66affSColin Finck 	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
681c2c66affSColin Finck                        wDevID, MCI_NOTIFY_SUCCESSFUL);
682c2c66affSColin Finck     }
683c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
684c2c66affSColin Finck     return dwRet;
685c2c66affSColin Finck }
686c2c66affSColin Finck 
687c2c66affSColin Finck /***************************************************************************
688c2c66affSColin Finck  * 				MCIAVI_mciPause			[internal]
689c2c66affSColin Finck  */
MCIAVI_mciPause(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)690c2c66affSColin Finck static	DWORD	MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
691c2c66affSColin Finck {
692c2c66affSColin Finck     WINE_MCIAVI *wma;
693c2c66affSColin Finck 
694c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
695c2c66affSColin Finck 
696c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
697c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
698c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
699c2c66affSColin Finck 
700c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
701c2c66affSColin Finck 
702c2c66affSColin Finck     if (wma->dwStatus == MCI_MODE_PLAY)
703c2c66affSColin Finck 	wma->dwStatus = MCI_MODE_PAUSE;
704c2c66affSColin Finck 
705c2c66affSColin Finck     if (wma->lpWaveFormat) {
706c2c66affSColin Finck     	LeaveCriticalSection(&wma->cs);
707c2c66affSColin Finck 	return waveOutPause(wma->hWave);
708c2c66affSColin Finck     }
709c2c66affSColin Finck 
710c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
711c2c66affSColin Finck     return 0;
712c2c66affSColin Finck }
713c2c66affSColin Finck 
714c2c66affSColin Finck /***************************************************************************
715c2c66affSColin Finck  * 				MCIAVI_mciResume			[internal]
716c2c66affSColin Finck  */
MCIAVI_mciResume(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)717c2c66affSColin Finck static	DWORD	MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
718c2c66affSColin Finck {
719c2c66affSColin Finck     WINE_MCIAVI *wma;
720c2c66affSColin Finck 
721c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
722c2c66affSColin Finck 
723c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
724c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
725c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
726c2c66affSColin Finck 
727c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
728c2c66affSColin Finck 
729c2c66affSColin Finck     if (wma->dwStatus == MCI_MODE_PAUSE)
730c2c66affSColin Finck 	wma->dwStatus = MCI_MODE_PLAY;
731c2c66affSColin Finck 
732c2c66affSColin Finck     if (wma->lpWaveFormat) {
733c2c66affSColin Finck     	LeaveCriticalSection(&wma->cs);
734c2c66affSColin Finck 	return waveOutRestart(wma->hWave);
735c2c66affSColin Finck     }
736c2c66affSColin Finck 
737c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
738c2c66affSColin Finck     return 0;
739c2c66affSColin Finck }
740c2c66affSColin Finck 
741c2c66affSColin Finck /***************************************************************************
742c2c66affSColin Finck  * 				MCIAVI_mciSeek			[internal]
743c2c66affSColin Finck  */
MCIAVI_mciSeek(UINT wDevID,DWORD dwFlags,LPMCI_SEEK_PARMS lpParms)744c2c66affSColin Finck static	DWORD	MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
745c2c66affSColin Finck {
746c2c66affSColin Finck     WINE_MCIAVI *wma;
747c2c66affSColin Finck     DWORD position;
748c2c66affSColin Finck 
749c2c66affSColin Finck     TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
750c2c66affSColin Finck 
751c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
752c2c66affSColin Finck 
753c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
754c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
755c2c66affSColin Finck 
756c2c66affSColin Finck     position = dwFlags & (MCI_SEEK_TO_START|MCI_SEEK_TO_END|MCI_TO);
757c2c66affSColin Finck     if (!position)		return MCIERR_MISSING_PARAMETER;
758c2c66affSColin Finck     if (position&(position-1))	return MCIERR_FLAGS_NOT_COMPATIBLE;
759c2c66affSColin Finck 
760c2c66affSColin Finck     if (dwFlags & MCI_TO) {
761c2c66affSColin Finck 	position = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
762c2c66affSColin Finck 	if (position >= wma->dwPlayableVideoFrames)
763c2c66affSColin Finck 	    return MCIERR_OUTOFRANGE;
764c2c66affSColin Finck     } else if (dwFlags & MCI_SEEK_TO_START) {
765c2c66affSColin Finck 	position = 0;
766c2c66affSColin Finck     } else {
767c2c66affSColin Finck 	position = wma->dwPlayableVideoFrames - 1;
768c2c66affSColin Finck     }
769c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
770c2c66affSColin Finck 
771c2c66affSColin Finck     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
772c2c66affSColin Finck 
773c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
774c2c66affSColin Finck 
775c2c66affSColin Finck     wma->dwCurrVideoFrame = position;
776c2c66affSColin Finck     TRACE("Seeking to frame=%u\n", wma->dwCurrVideoFrame);
777c2c66affSColin Finck 
778c2c66affSColin Finck     if (dwFlags & MCI_NOTIFY) {
779c2c66affSColin Finck 	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
780c2c66affSColin Finck                        wDevID, MCI_NOTIFY_SUCCESSFUL);
781c2c66affSColin Finck     }
782c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
783c2c66affSColin Finck     return 0;
784c2c66affSColin Finck }
785c2c66affSColin Finck 
786c2c66affSColin Finck /*****************************************************************************
787c2c66affSColin Finck  * 				MCIAVI_mciLoad			[internal]
788c2c66affSColin Finck  */
MCIAVI_mciLoad(UINT wDevID,DWORD dwFlags,LPMCI_DGV_LOAD_PARMSW lpParms)789c2c66affSColin Finck static DWORD	MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSW lpParms)
790c2c66affSColin Finck {
791c2c66affSColin Finck     WINE_MCIAVI *wma;
792c2c66affSColin Finck 
793c2c66affSColin Finck     FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
794c2c66affSColin Finck 
795c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
796c2c66affSColin Finck 
797c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
798c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
799c2c66affSColin Finck 
800c2c66affSColin Finck     return MCIERR_UNSUPPORTED_FUNCTION; /* like w2k */
801c2c66affSColin Finck }
802c2c66affSColin Finck 
803c2c66affSColin Finck /******************************************************************************
804c2c66affSColin Finck  * 				MCIAVI_mciRealize			[internal]
805c2c66affSColin Finck  */
MCIAVI_mciRealize(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)806c2c66affSColin Finck static	DWORD	MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
807c2c66affSColin Finck {
808c2c66affSColin Finck     WINE_MCIAVI *wma;
809c2c66affSColin Finck 
810c2c66affSColin Finck     FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
811c2c66affSColin Finck 
812c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
813c2c66affSColin Finck 
814c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
815c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
816c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
817c2c66affSColin Finck 
818c2c66affSColin Finck     return 0;
819c2c66affSColin Finck }
820c2c66affSColin Finck 
821c2c66affSColin Finck /******************************************************************************
822c2c66affSColin Finck  * 				MCIAVI_mciUpdate			[internal]
823c2c66affSColin Finck  */
MCIAVI_mciUpdate(UINT wDevID,DWORD dwFlags,LPMCI_DGV_UPDATE_PARMS lpParms)824c2c66affSColin Finck static	DWORD	MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
825c2c66affSColin Finck {
826c2c66affSColin Finck     WINE_MCIAVI *wma;
827c2c66affSColin Finck 
828c2c66affSColin Finck     TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms);
829c2c66affSColin Finck 
830c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
831c2c66affSColin Finck 
832c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
833c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
834c2c66affSColin Finck     /* Ignore MCI_TEST flag. */
835c2c66affSColin Finck 
836c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
837c2c66affSColin Finck 
838c2c66affSColin Finck     if (dwFlags & MCI_DGV_UPDATE_HDC)
839c2c66affSColin Finck         MCIAVI_PaintFrame(wma, lpParms->hDC);
840c2c66affSColin Finck 
841c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
842c2c66affSColin Finck 
843c2c66affSColin Finck     return 0;
844c2c66affSColin Finck }
845c2c66affSColin Finck 
846c2c66affSColin Finck /******************************************************************************
847c2c66affSColin Finck  * 				MCIAVI_mciStep			[internal]
848c2c66affSColin Finck  */
MCIAVI_mciStep(UINT wDevID,DWORD dwFlags,LPMCI_DGV_STEP_PARMS lpParms)849c2c66affSColin Finck static	DWORD	MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
850c2c66affSColin Finck {
851c2c66affSColin Finck     WINE_MCIAVI *wma;
852c2c66affSColin Finck     DWORD position;
853c2c66affSColin Finck     int delta = 1;
854c2c66affSColin Finck 
855c2c66affSColin Finck     TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms);
856c2c66affSColin Finck 
857c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
858c2c66affSColin Finck 
859c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
860c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
861c2c66affSColin Finck 
862c2c66affSColin Finck     if (dwFlags & MCI_DGV_STEP_FRAMES)  delta = lpParms->dwFrames;
863c2c66affSColin Finck     if (dwFlags & MCI_DGV_STEP_REVERSE) delta = -delta;
864c2c66affSColin Finck     position = wma->dwCurrVideoFrame + delta;
865c2c66affSColin Finck     if (position >= wma->dwPlayableVideoFrames) return MCIERR_OUTOFRANGE;
866c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
867c2c66affSColin Finck 
868c2c66affSColin Finck     MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
869c2c66affSColin Finck 
870c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
871c2c66affSColin Finck 
872c2c66affSColin Finck     wma->dwCurrVideoFrame = position;
873c2c66affSColin Finck     TRACE("Stepping to frame=%u\n", wma->dwCurrVideoFrame);
874c2c66affSColin Finck 
875c2c66affSColin Finck     if (dwFlags & MCI_NOTIFY) {
876c2c66affSColin Finck 	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
877c2c66affSColin Finck                        wDevID, MCI_NOTIFY_SUCCESSFUL);
878c2c66affSColin Finck     }
879c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
880c2c66affSColin Finck     return 0;
881c2c66affSColin Finck }
882c2c66affSColin Finck 
883c2c66affSColin Finck /******************************************************************************
884c2c66affSColin Finck  * 				MCIAVI_mciCue			[internal]
885c2c66affSColin Finck  */
MCIAVI_mciCue(UINT wDevID,DWORD dwFlags,LPMCI_DGV_CUE_PARMS lpParms)886c2c66affSColin Finck static	DWORD	MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
887c2c66affSColin Finck {
888c2c66affSColin Finck     WINE_MCIAVI *wma;
889c2c66affSColin Finck 
890c2c66affSColin Finck     FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
891c2c66affSColin Finck 
892c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
893c2c66affSColin Finck 
894c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
895c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
896c2c66affSColin Finck     if (dwFlags & MCI_DGV_CUE_INPUT) return MCIERR_UNSUPPORTED_FUNCTION;
897c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
898c2c66affSColin Finck 
899c2c66affSColin Finck     return 0;
900c2c66affSColin Finck }
901c2c66affSColin Finck 
902c2c66affSColin Finck /******************************************************************************
903c2c66affSColin Finck  * 				MCIAVI_mciBreak			[internal]
904c2c66affSColin Finck  */
MCIAVI_mciBreak(UINT wDevID,DWORD dwFlags,LPMCI_BREAK_PARMS lpParms)905c2c66affSColin Finck static	DWORD	MCIAVI_mciBreak(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms)
906c2c66affSColin Finck {
907c2c66affSColin Finck     WINE_MCIAVI *wma;
908c2c66affSColin Finck 
909c2c66affSColin Finck     TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms);
910c2c66affSColin Finck 
911c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
912c2c66affSColin Finck 
913c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
914c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
915c2c66affSColin Finck 
916c2c66affSColin Finck     EnterCriticalSection(&wma->cs);
917c2c66affSColin Finck 
918c2c66affSColin Finck     wma->mci_break.flags = dwFlags;
919c2c66affSColin Finck     wma->mci_break.parms = *lpParms;
920c2c66affSColin Finck 
921c2c66affSColin Finck     LeaveCriticalSection(&wma->cs);
922c2c66affSColin Finck 
923c2c66affSColin Finck     return 0;
924c2c66affSColin Finck }
925c2c66affSColin Finck 
926c2c66affSColin Finck /******************************************************************************
927c2c66affSColin Finck  * 				MCIAVI_mciSetAudio			[internal]
928c2c66affSColin Finck  */
MCIAVI_mciSetAudio(UINT wDevID,DWORD dwFlags,LPMCI_DGV_SETAUDIO_PARMSW lpParms)929c2c66affSColin Finck static	DWORD	MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms)
930c2c66affSColin Finck {
931c2c66affSColin Finck     WINE_MCIAVI *wma;
932c2c66affSColin Finck 
933c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
934c2c66affSColin Finck 
935c2c66affSColin Finck     FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETAUDIO_ITEM ? lpParms->dwItem : 0);
936c2c66affSColin Finck 
937c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
938c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
939c2c66affSColin Finck 
940c2c66affSColin Finck     return 0;
941c2c66affSColin Finck }
942c2c66affSColin Finck 
943c2c66affSColin Finck /******************************************************************************
944c2c66affSColin Finck  * 				MCIAVI_mciSignal			[internal]
945c2c66affSColin Finck  */
MCIAVI_mciSignal(UINT wDevID,DWORD dwFlags,LPMCI_DGV_SIGNAL_PARMS lpParms)946c2c66affSColin Finck static	DWORD	MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
947c2c66affSColin Finck {
948c2c66affSColin Finck     WINE_MCIAVI *wma;
949c2c66affSColin Finck 
950c2c66affSColin Finck     FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
951c2c66affSColin Finck 
952c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
953c2c66affSColin Finck 
954c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
955c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
956c2c66affSColin Finck 
957c2c66affSColin Finck     return 0;
958c2c66affSColin Finck }
959c2c66affSColin Finck 
960c2c66affSColin Finck /******************************************************************************
961c2c66affSColin Finck  * 				MCIAVI_mciSetVideo			[internal]
962c2c66affSColin Finck  */
MCIAVI_mciSetVideo(UINT wDevID,DWORD dwFlags,LPMCI_DGV_SETVIDEO_PARMSW lpParms)963c2c66affSColin Finck static	DWORD	MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSW lpParms)
964c2c66affSColin Finck {
965c2c66affSColin Finck     WINE_MCIAVI *wma;
966c2c66affSColin Finck 
967c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
968c2c66affSColin Finck 
969c2c66affSColin Finck     FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETVIDEO_ITEM ? lpParms->dwItem : 0);
970c2c66affSColin Finck 
971c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
972c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
973c2c66affSColin Finck 
974c2c66affSColin Finck     return 0;
975c2c66affSColin Finck }
976c2c66affSColin Finck 
977c2c66affSColin Finck /******************************************************************************
978c2c66affSColin Finck  * 				MCIAVI_mciConfigure			[internal]
979c2c66affSColin Finck  */
MCIAVI_mciConfigure(UINT wDevID,DWORD dwFlags,LPMCI_GENERIC_PARMS lpParms)980c2c66affSColin Finck static	DWORD	MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
981c2c66affSColin Finck {
982c2c66affSColin Finck     WINE_MCIAVI *wma;
983c2c66affSColin Finck 
984c2c66affSColin Finck     FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
985c2c66affSColin Finck 
986c2c66affSColin Finck     if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
987c2c66affSColin Finck 
988c2c66affSColin Finck     wma = MCIAVI_mciGetOpenDev(wDevID);
989c2c66affSColin Finck     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
990c2c66affSColin Finck     if (dwFlags & MCI_TEST)	return 0;
991c2c66affSColin Finck 
992c2c66affSColin Finck     return 0;
993c2c66affSColin Finck }
994c2c66affSColin Finck 
995c2c66affSColin Finck /*======================================================================*
996c2c66affSColin Finck  *                  	    MCI AVI entry points			*
997c2c66affSColin Finck  *======================================================================*/
998c2c66affSColin Finck 
999c2c66affSColin Finck /**************************************************************************
1000c2c66affSColin Finck  * 				DriverProc (MCIAVI.@)
1001c2c66affSColin Finck  */
MCIAVI_DriverProc(DWORD_PTR dwDevID,HDRVR hDriv,UINT wMsg,LPARAM dwParam1,LPARAM dwParam2)1002c2c66affSColin Finck LRESULT CALLBACK MCIAVI_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1003c2c66affSColin Finck                                    LPARAM dwParam1, LPARAM dwParam2)
1004c2c66affSColin Finck {
1005c2c66affSColin Finck     TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
1006c2c66affSColin Finck 	  dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1007c2c66affSColin Finck 
1008c2c66affSColin Finck     switch (wMsg) {
1009c2c66affSColin Finck     case DRV_LOAD:		return 1;
1010c2c66affSColin Finck     case DRV_FREE:		return 1;
1011c2c66affSColin Finck     case DRV_OPEN:		return MCIAVI_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2);
1012c2c66affSColin Finck     case DRV_CLOSE:		return MCIAVI_drvClose(dwDevID);
1013c2c66affSColin Finck     case DRV_ENABLE:		return 1;
1014c2c66affSColin Finck     case DRV_DISABLE:		return 1;
1015c2c66affSColin Finck     case DRV_QUERYCONFIGURE:	return 1;
1016c2c66affSColin Finck     case DRV_CONFIGURE:		return MCIAVI_drvConfigure(dwDevID);
1017c2c66affSColin Finck     case DRV_INSTALL:		return DRVCNF_RESTART;
1018c2c66affSColin Finck     case DRV_REMOVE:		return DRVCNF_RESTART;
1019c2c66affSColin Finck     }
1020c2c66affSColin Finck 
1021c2c66affSColin Finck     /* session instance */
1022c2c66affSColin Finck     if (dwDevID == 0xFFFFFFFF) return 1;
1023c2c66affSColin Finck 
1024c2c66affSColin Finck     switch (wMsg) {
1025c2c66affSColin Finck     case MCI_OPEN_DRIVER:	return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW)     dwParam2);
1026c2c66affSColin Finck     case MCI_CLOSE_DRIVER:	return MCIAVI_mciClose     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1027c2c66affSColin Finck     case MCI_PLAY:		return MCIAVI_mciPlay      (dwDevID, dwParam1, (LPMCI_PLAY_PARMS)          dwParam2);
1028c2c66affSColin Finck     case MCI_STOP:		return MCIAVI_mciStop      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1029c2c66affSColin Finck     case MCI_SET:		return MCIAVI_mciSet       (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS)       dwParam2);
1030c2c66affSColin Finck     case MCI_PAUSE:		return MCIAVI_mciPause     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1031c2c66affSColin Finck     case MCI_RESUME:		return MCIAVI_mciResume    (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1032c2c66affSColin Finck     case MCI_STATUS:		return MCIAVI_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW)   dwParam2);
1033c2c66affSColin Finck     case MCI_GETDEVCAPS:	return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
1034c2c66affSColin Finck     case MCI_INFO:		return MCIAVI_mciInfo      (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW)     dwParam2);
1035c2c66affSColin Finck     case MCI_SEEK:		return MCIAVI_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
1036c2c66affSColin Finck     case MCI_PUT:		return MCIAVI_mciPut	   (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS)       dwParam2);
1037c2c66affSColin Finck     case MCI_WINDOW:		return MCIAVI_mciWindow	   (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW)   dwParam2);
1038c2c66affSColin Finck     case MCI_LOAD:		return MCIAVI_mciLoad      (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSW)     dwParam2);
1039c2c66affSColin Finck     case MCI_REALIZE:		return MCIAVI_mciRealize   (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1040c2c66affSColin Finck     case MCI_UPDATE:		return MCIAVI_mciUpdate    (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)    dwParam2);
1041c2c66affSColin Finck     case MCI_WHERE:		return MCIAVI_mciWhere	   (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
1042c2c66affSColin Finck     case MCI_STEP:		return MCIAVI_mciStep      (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS)      dwParam2);
1043c2c66affSColin Finck     case MCI_CUE:		return MCIAVI_mciCue       (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS)       dwParam2);
1044c2c66affSColin Finck     case MCI_BREAK:		return MCIAVI_mciBreak     (dwDevID, dwParam1, (LPMCI_BREAK_PARMS)         dwParam2);
1045c2c66affSColin Finck 	/* Digital Video specific */
1046c2c66affSColin Finck     case MCI_SETAUDIO:		return MCIAVI_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
1047c2c66affSColin Finck     case MCI_SIGNAL:		return MCIAVI_mciSignal    (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS)    dwParam2);
1048c2c66affSColin Finck     case MCI_SETVIDEO:		return MCIAVI_mciSetVideo  (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSW) dwParam2);
1049c2c66affSColin Finck     case MCI_CONFIGURE:		return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1050c2c66affSColin Finck 
1051c2c66affSColin Finck 	/* no editing, recording, saving, locking without inputs */
1052c2c66affSColin Finck     case MCI_CAPTURE:
1053c2c66affSColin Finck     case MCI_COPY:
1054c2c66affSColin Finck     case MCI_CUT:
1055c2c66affSColin Finck     case MCI_DELETE:
1056c2c66affSColin Finck     case MCI_FREEZE:
1057c2c66affSColin Finck     case MCI_LIST:
1058c2c66affSColin Finck     case MCI_MONITOR:
1059c2c66affSColin Finck     case MCI_PASTE:
1060c2c66affSColin Finck     case MCI_QUALITY:
1061c2c66affSColin Finck     case MCI_RECORD:
1062c2c66affSColin Finck     case MCI_RESERVE:
1063c2c66affSColin Finck     case MCI_RESTORE:
1064c2c66affSColin Finck     case MCI_SAVE:
1065c2c66affSColin Finck     case MCI_UNDO:
1066c2c66affSColin Finck     case MCI_UNFREEZE:
1067c2c66affSColin Finck 	TRACE("Unsupported function [0x%x] flags=%08x\n", wMsg, (DWORD)dwParam1);
1068c2c66affSColin Finck 	return MCIERR_UNSUPPORTED_FUNCTION;
1069c2c66affSColin Finck     case MCI_SPIN:
1070c2c66affSColin Finck     case MCI_ESCAPE:
1071c2c66affSColin Finck 	WARN("Unsupported command [0x%x] %08x\n", wMsg, (DWORD)dwParam1);
1072c2c66affSColin Finck 	break;
1073c2c66affSColin Finck     case MCI_OPEN:
1074c2c66affSColin Finck     case MCI_CLOSE:
1075c2c66affSColin Finck 	FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1076c2c66affSColin Finck 	break;
1077c2c66affSColin Finck     default:
1078c2c66affSColin Finck 	TRACE("Sending msg [%u] to default driver proc\n", wMsg);
1079c2c66affSColin Finck 	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1080c2c66affSColin Finck     }
1081c2c66affSColin Finck     return MCIERR_UNRECOGNIZED_COMMAND;
1082c2c66affSColin Finck }
1083