mciavi.c 38.5 KB
Newer Older
1 2 3
/*
 * Digital video MCI Wine Driver
 *
4
 * Copyright 1999, 2000 Eric POUECH
5
 * Copyright 2003 Dmitry Timoshkov
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21 22 23 24 25 26 27 28 29 30 31
 */

/* TODO list :
 *	- handling of palettes
 *	- recording (which input devices ?), a cam recorder ?
 *	- lots of messages still need to be handled (cf FIXME)
 *	- synchronization between audio and video (especially for interleaved
 *	  files)
 *	- robustness when reading file can be enhanced
 *	- better move the AVI handling part to avifile DLL and make use of it
 *	- some files appear to have more than one audio stream (we only play the
 *	  first one)
32
 *	- some files contain an index of audio/video frame. Better use it,
33 34 35
 *	  instead of rebuilding it
 *	- stopping while playing a file with sound blocks until all buffered
 *        audio is played... still should be stopped ASAP
36 37
 */

38
#include <string.h>
39
#include "private_mciavi.h"
40
#include "wine/debug.h"
41
#include "wine/unicode.h"
42

43
WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
44

45 46
static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);

47
/*======================================================================*
48
 *                  	    MCI AVI implementation			*
49 50
 *======================================================================*/

51 52
HINSTANCE MCIAVI_hInstance = 0;

53 54 55
/***********************************************************************
 *		DllMain (MCIAVI.0)
 */
56
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
57 58 59
{
    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
60
        DisableThreadLibraryCalls(hInstDLL);
61 62 63 64 65 66
	MCIAVI_hInstance = hInstDLL;
	break;
    }
    return TRUE;
}

67
/**************************************************************************
68
 * 				MCIAVI_drvOpen			[internal]
69
 */
70
static	DWORD	MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
71
{
72
    WINE_MCIAVI*	wma;
73
    static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
74

75
    TRACE("%s, %p\n", debugstr_w(str), modp);
76 77

    /* session instance */
78 79
    if (!modp) return 0xFFFFFFFF;

80 81
    if (!MCIAVI_RegisterClass()) return 0;

82
    wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
83 84
    if (!wma)
	return 0;
85

86
    InitializeCriticalSection(&wma->cs);
87
    wma->ack_event = CreateEventW(NULL, FALSE, FALSE, NULL);
88
    wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
89
    wma->wDevID = modp->wDeviceID;
90 91
    wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
    modp->wCustomCommandTable = wma->wCommandTable;
92
    modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
93 94
    mciSetDriverData(wma->wDevID, (DWORD)wma);

95
    return modp->wDeviceID;
96 97 98
}

/**************************************************************************
99
 * 				MCIAVI_drvClose		[internal]
100
 */
101
static	DWORD	MCIAVI_drvClose(DWORD dwDevID)
102
{
103 104
    WINE_MCIAVI *wma;

105
    TRACE("%04x\n", dwDevID);
106 107 108 109 110

    /* finish all outstanding things */
    MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL);

    wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
111

112
    if (wma) {
113 114
        MCIAVI_UnregisterClass();

115 116
        EnterCriticalSection(&wma->cs);

117
	mciSetDriverData(dwDevID, 0);
118
	mciFreeCommandResource(wma->wCommandTable);
119

120
        CloseHandle(wma->ack_event);
121 122
        CloseHandle(wma->hStopEvent);

123 124 125
        LeaveCriticalSection(&wma->cs);
        DeleteCriticalSection(&wma->cs);

126
	HeapFree(GetProcessHeap(), 0, wma);
127 128
	return 1;
    }
129
    return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
130 131 132
}

/**************************************************************************
133
 * 				MCIAVI_drvConfigure		[internal]
134 135 136
 */
static	DWORD	MCIAVI_drvConfigure(DWORD dwDevID)
{
137 138
    WINE_MCIAVI *wma;

139
    TRACE("%04x\n", dwDevID);
140 141 142 143

    MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);

    wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
144 145

    if (wma) {
146
	MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
147 148 149 150 151
	return 1;
    }
    return 0;
}

152
/**************************************************************************
153
 * 				MCIAVI_mciGetOpenDev		[internal]
154
 */
155
WINE_MCIAVI*  MCIAVI_mciGetOpenDev(UINT wDevID)
156
{
157
    WINE_MCIAVI*	wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
158

159
    if (wma == NULL || wma->nUseCount == 0) {
160
	WARN("Invalid wDevID=%u\n", wDevID);
161 162
	return 0;
    }
163
    return wma;
164 165
}

166 167 168 169 170 171 172
static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
{
    /* to prevent handling in WindowProc */
    wma->dwStatus = MCI_MODE_NOT_READY;
    if (wma->hFile) {
	mmioClose(wma->hFile, 0);
	wma->hFile = 0;
173

174
        HeapFree(GetProcessHeap(), 0, wma->lpFileName);
175 176
        wma->lpFileName = NULL;

177
        HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
178
	wma->lpVideoIndex = NULL;
179
        HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
180 181 182
	wma->lpAudioIndex = NULL;
	if (wma->hic)		ICClose(wma->hic);
	wma->hic = 0;
183
        HeapFree(GetProcessHeap(), 0, wma->inbih);
184
	wma->inbih = NULL;
185
        HeapFree(GetProcessHeap(), 0, wma->outbih);
186
	wma->outbih = NULL;
187
        HeapFree(GetProcessHeap(), 0, wma->indata);
188
	wma->indata = NULL;
189
        HeapFree(GetProcessHeap(), 0, wma->outdata);
190 191 192 193 194
	wma->outdata = NULL;
    	if (wma->hbmFrame)	DeleteObject(wma->hbmFrame);
	wma->hbmFrame = 0;
	if (wma->hWnd)		DestroyWindow(wma->hWnd);
	wma->hWnd = 0;
195

196
        HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
197 198 199 200 201 202
	wma->lpWaveFormat = 0;

	memset(&wma->mah, 0, sizeof(wma->mah));
	memset(&wma->ash_video, 0, sizeof(wma->ash_video));
	memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
	wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
203
        wma->dwCachedFrame = -1;
204 205 206
    }
}

207
/***************************************************************************
208
 * 				MCIAVI_mciOpen			[internal]
209
 */
210
static	DWORD	MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
211
                               LPMCI_DGV_OPEN_PARMSW lpOpenParms)
212
{
213
    WINE_MCIAVI *wma;
214
    LRESULT		dwRet = 0;
215

216
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
217

218 219
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

220
    if (lpOpenParms == NULL) 		return MCIERR_NULL_PARAMETER_BLOCK;
221 222

    wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
223
    if (wma == NULL)			return MCIERR_INVALID_DEVICE_ID;
224

225 226
    EnterCriticalSection(&wma->cs);

227 228 229 230 231 232 233
    if (wma->nUseCount > 0) {
	/* The driver is already open on this channel */
	/* If the driver was opened shareable before and this open specifies */
	/* shareable then increment the use count */
	if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
	    ++wma->nUseCount;
	else
234 235
        {
            LeaveCriticalSection(&wma->cs);
236
	    return MCIERR_MUST_USE_SHAREABLE;
237
        }
238 239 240 241
    } else {
	wma->nUseCount = 1;
	wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
    }
242 243 244

    wma->dwStatus = MCI_MODE_NOT_READY;

245
    if (dwFlags & MCI_OPEN_ELEMENT) {
246
	if (dwFlags & MCI_OPEN_ELEMENT_ID) {
247 248
	    /* could it be that (DWORD)lpOpenParms->lpstrElementName
	     * contains the hFile value ?
249 250
	     */
	    dwRet = MCIERR_UNRECOGNIZED_COMMAND;
251
	} else if (strlenW(lpOpenParms->lpstrElementName) > 0) {
252
	    /* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
253
	    TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(lpOpenParms->lpstrElementName));
254

255
            if (lpOpenParms->lpstrElementName && (strlenW(lpOpenParms->lpstrElementName) > 0))
256
            {
257 258
                wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpOpenParms->lpstrElementName) + 1) * sizeof(WCHAR));
                strcpyW(wma->lpFileName, lpOpenParms->lpstrElementName);
259

260
		wma->hFile = mmioOpenW(lpOpenParms->lpstrElementName, NULL,
261
				       MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READ);
262

263
		if (wma->hFile == 0) {
264
		    WARN("can't find file=%s!\n", debugstr_w(lpOpenParms->lpstrElementName));
265 266
		    dwRet = MCIERR_FILE_NOT_FOUND;
		} else {
267
		    if (!MCIAVI_GetInfo(wma))
268 269 270 271 272
			dwRet = MCIERR_INVALID_FILE;
		    else if (!MCIAVI_OpenVideo(wma))
			dwRet = MCIERR_CANNOT_LOAD_DRIVER;
		    else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
			dwRet = MCIERR_CREATEWINDOW;
273
		}
274 275 276 277 278
	    }
	} else {
	    FIXME("Don't record yet\n");
	    dwRet = MCIERR_UNSUPPORTED_FUNCTION;
	}
279
    }
280

281
    if (dwRet == 0) {
282 283
        TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID);

284 285 286 287 288
	wma->dwStatus = MCI_MODE_STOP;
	wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
    } else {
	MCIAVI_CleanUp(wma);
    }
289

290 291
    LeaveCriticalSection(&wma->cs);
    return dwRet;
292 293
}

294
/***************************************************************************
295
 * 				MCIAVI_mciClose			[internal]
296
 */
297
DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
298
{
299
    WINE_MCIAVI *wma;
300
    DWORD		dwRet = 0;
301

302
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
303

304 305 306
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

    wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
307
    if (wma == NULL) 	return MCIERR_INVALID_DEVICE_ID;
308

309 310
    EnterCriticalSection(&wma->cs);

311
    if (wma->nUseCount == 1) {
312
	if (wma->dwStatus != MCI_MODE_STOP)
313
           dwRet = MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
314
    	MCIAVI_CleanUp(wma);
315

316
	if ((dwFlags & MCI_NOTIFY) && lpParms) {
317
	    mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
318
                           wDevID,
319 320
			    MCI_NOTIFY_SUCCESSFUL);
	}
321
        LeaveCriticalSection(&wma->cs);
322
	return dwRet;
323 324
    }
    wma->nUseCount--;
325 326

    LeaveCriticalSection(&wma->cs);
327
    return dwRet;
328 329
}

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms);

struct MCIAVI_play_data
{
    MCIDEVICEID wDevID;
    DWORD flags;
    MCI_PLAY_PARMS params;
};

/*
 * MCIAVI_mciPlay_thread
 *
 * FIXME: probably should use a common worker thread created at the driver
 * load time and queue all async commands to it.
 */
static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg)
{
    struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg;
    DWORD ret;

350
    TRACE("In thread before async play command (id %08x, flags %08x)\n", data->wDevID, data->flags);
351
    ret = MCIAVI_mciPlay(data->wDevID, data->flags | MCI_WAIT, &data->params);
352
    TRACE("In thread after async play command (id %08x, flags %08x)\n", data->wDevID, data->flags);
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384

    HeapFree(GetProcessHeap(), 0, data);
    return ret;
}

/*
 * MCIAVI_mciPlay_async
 */
static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams)
{
    HANDLE handle, ack_event = wma->ack_event;
    struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data));

    if (!data) return MCIERR_OUT_OF_MEMORY;

    data->wDevID = wma->wDevID;
    data->flags = dwFlags;
    memcpy(&data->params, lpParams, sizeof(MCI_PLAY_PARMS));

    if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL)))
    {
        WARN("Couldn't create thread for async play, playing synchronously\n");
        return MCIAVI_mciPlay_thread(data);
    }
    SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
    CloseHandle(handle);
    /* wait until the thread starts up, so the app could see a changed status */
    WaitForSingleObject(ack_event, INFINITE);
    TRACE("Async play has started\n");
    return 0;
}

385
/***************************************************************************
386
 * 				MCIAVI_mciPlay			[internal]
387
 */
388
static	DWORD	MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
389
{
390
    WINE_MCIAVI *wma;
391 392 393 394 395 396 397
    DWORD		tc;
    DWORD		frameTime;
    DWORD		delta;
    DWORD		dwRet;
    LPWAVEHDR		waveHdr = NULL;
    unsigned		i, nHdr = 0;
    DWORD		dwFromFrame, dwToFrame;
398

399
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
400

401
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
402 403

    wma = (WINE_MCIAVI *)MCIAVI_mciGetOpenDev(wDevID);
404
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
405

406 407 408 409 410 411 412 413 414 415 416 417
    EnterCriticalSection(&wma->cs);

    if (!wma->hFile)
    {
        LeaveCriticalSection(&wma->cs);
        return MCIERR_FILE_NOT_FOUND;
    }
    if (!wma->hWndPaint)
    {
        LeaveCriticalSection(&wma->cs);
        return MCIERR_NO_WINDOW;
    }
418

419
    LeaveCriticalSection(&wma->cs);
420

421 422
    if (!(dwFlags & MCI_WAIT))
        return MCIAVI_mciPlay_async(wma, dwFlags, lpParms);
423

424 425
    if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
        ShowWindow(wma->hWndPaint, SW_SHOWNA);
426 427

    EnterCriticalSection(&wma->cs);
428

429 430
    dwFromFrame = wma->dwCurrVideoFrame;
    dwToFrame = wma->dwPlayableVideoFrames - 1;
431

432
    if (lpParms && (dwFlags & MCI_FROM)) {
433
	dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
434 435 436 437 438 439
    }
    if (lpParms && (dwFlags & MCI_TO)) {
	dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
    }
    if (dwToFrame >= wma->dwPlayableVideoFrames)
	dwToFrame = wma->dwPlayableVideoFrames - 1;
440

441
    TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame);
442

443
    wma->dwCurrVideoFrame = dwFromFrame;
444
    wma->dwToVideoFrame = dwToFrame;
445

446 447 448 449
    /* if already playing exit */
    if (wma->dwStatus == MCI_MODE_PLAY)
    {
        LeaveCriticalSection(&wma->cs);
450
        SetEvent(wma->ack_event);
451 452 453 454
        return 0;
    }

    if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
455 456
    {
        dwRet = 0;
457
        SetEvent(wma->ack_event);
458 459 460
        goto mci_play_done;
    }

461
    wma->dwStatus = MCI_MODE_PLAY;
462 463
    /* signal the state change */
    SetEvent(wma->ack_event);
464

465
    if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
466
	FIXME("Unsupported flag %08x\n", dwFlags);
467

468 469
    /* time is in microseconds, we should convert it to milliseconds */
    frameTime = (wma->mah.dwMicroSecPerFrame + 500) / 1000;
470

471
    if (wma->lpWaveFormat) {
472 473 474 475 476 477 478
       if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
        {
            /* can't play audio */
            HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
            wma->lpWaveFormat = NULL;
        }
        else
479 480
	/* fill the queue with as many wave headers as possible */
	MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
481
    }
482

483 484
    while (wma->dwStatus == MCI_MODE_PLAY)
    {
485
        HDC hDC;
486
        DWORD ret;
487

488
	tc = GetTickCount();
489

490 491 492 493 494 495
        hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
        if (hDC)
        {
            MCIAVI_PaintFrame(wma, hDC);
            ReleaseDC(wma->hWndPaint, hDC);
        }
496 497

	if (wma->lpWaveFormat) {
498 499 500 501 502
            HANDLE events[2];

            events[0] = wma->hStopEvent;
            events[1] = wma->hEvent;

503 504
	    MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
	    delta = GetTickCount() - tc;
505 506

            LeaveCriticalSection(&wma->cs);
507 508
            ret = MsgWaitForMultipleObjectsEx(2, events,
                (delta >= frameTime) ? 0 : frameTime - delta, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
509 510
            EnterCriticalSection(&wma->cs);

511
            if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
512
	}
513 514 515

	delta = GetTickCount() - tc;
	if (delta < frameTime)
516 517 518
            delta = frameTime - delta;
        else
            delta = 0;
519

520 521 522 523 524
        LeaveCriticalSection(&wma->cs);
        ret = MsgWaitForMultipleObjectsEx(1, &wma->hStopEvent, delta,
                                          QS_ALLINPUT, MWMO_INPUTAVAILABLE);
        EnterCriticalSection(&wma->cs);
        if (ret == WAIT_OBJECT_0) break;
525 526 527 528 529

       if (wma->dwCurrVideoFrame < dwToFrame)
           wma->dwCurrVideoFrame++;
        else
            break;
530
    }
531 532

    if (wma->lpWaveFormat) {
533 534 535 536 537 538
       while (wma->dwEventCount != nHdr - 1)
        {
            LeaveCriticalSection(&wma->cs);
            Sleep(100);
            EnterCriticalSection(&wma->cs);
        }
539

540
	/* just to get rid of some race conditions between play, stop and pause */
541
	LeaveCriticalSection(&wma->cs);
542
	waveOutReset(wma->hWave);
543
	EnterCriticalSection(&wma->cs);
544 545 546

	for (i = 0; i < nHdr; i++)
	    waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
547
    }
548

549
    dwRet = 0;
550

551 552
    if (wma->lpWaveFormat) {
	HeapFree(GetProcessHeap(), 0, waveHdr);
553

554
	if (wma->hWave) {
555
	    LeaveCriticalSection(&wma->cs);
556
	    waveOutClose(wma->hWave);
557
	    EnterCriticalSection(&wma->cs);
558
	    wma->hWave = 0;
559
	}
560
	CloseHandle(wma->hEvent);
561
    }
562

563 564 565
mci_play_done:
    wma->dwStatus = MCI_MODE_STOP;

566
    if (lpParms && (dwFlags & MCI_NOTIFY)) {
567
	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
568
	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
569
                       wDevID, MCI_NOTIFY_SUCCESSFUL);
570
    }
571
    LeaveCriticalSection(&wma->cs);
572
    return dwRet;
573 574
}

575
/***************************************************************************
576
 * 				MCIAVI_mciRecord			[internal]
577
 */
578
static	DWORD	MCIAVI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECORD_PARMS lpParms)
579
{
580
    WINE_MCIAVI *wma;
581

582
    FIXME("(%04x, %08X, %p) : stub\n", wDevID, dwFlags, lpParms);
583

584 585
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

586
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
587 588

    wma = MCIAVI_mciGetOpenDev(wDevID);
589
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
590

591
    EnterCriticalSection(&wma->cs);
592
    wma->dwStatus = MCI_MODE_RECORD;
593
    LeaveCriticalSection(&wma->cs);
594
    return 0;
595 596
}

597
/***************************************************************************
598
 * 				MCIAVI_mciStop			[internal]
599
 */
600
static	DWORD	MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
601
{
602
    WINE_MCIAVI *wma;
603
    DWORD		dwRet = 0;
604

605
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
606

607
    wma = MCIAVI_mciGetOpenDev(wDevID);
608
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
609

610 611
    EnterCriticalSection(&wma->cs);

612
    TRACE("current status %04x\n", wma->dwStatus);
613

614 615 616
    switch (wma->dwStatus) {
    case MCI_MODE_PLAY:
    case MCI_MODE_RECORD:
617
        LeaveCriticalSection(&wma->cs);
618
        SetEvent(wma->hStopEvent);
619
        EnterCriticalSection(&wma->cs);
620 621
        /* fall through */
    case MCI_MODE_PAUSE:
622 623 624
	/* Since our wave notification callback takes the lock,
	 * we must release it before resetting the device */
        LeaveCriticalSection(&wma->cs);
625
        dwRet = waveOutReset(wma->hWave);
626
        EnterCriticalSection(&wma->cs);
627
        /* fall through */
628
    default:
629 630 631
        do /* one more chance for an async thread to finish */
        {
            LeaveCriticalSection(&wma->cs);
632
            Sleep(10);
633 634 635
            EnterCriticalSection(&wma->cs);
        } while (wma->dwStatus != MCI_MODE_STOP);

636
	break;
637 638 639

    case MCI_MODE_NOT_READY:
        break;        
640
    }
641

642
    if ((dwFlags & MCI_NOTIFY) && lpParms) {
643
	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
644
                       wDevID, MCI_NOTIFY_SUCCESSFUL);
645
    }
646
    LeaveCriticalSection(&wma->cs);
647
    return dwRet;
648 649
}

650
/***************************************************************************
651
 * 				MCIAVI_mciPause			[internal]
652
 */
653
static	DWORD	MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
654
{
655
    WINE_MCIAVI *wma;
656

657
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
658

659
    wma = MCIAVI_mciGetOpenDev(wDevID);
660
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
661

662 663
    EnterCriticalSection(&wma->cs);

664 665 666
    if (wma->dwStatus == MCI_MODE_PLAY)
	wma->dwStatus = MCI_MODE_PAUSE;

667 668 669 670
    if (wma->lpWaveFormat) {
    	LeaveCriticalSection(&wma->cs);
	return waveOutPause(wma->hWave);
    }
671

672
    LeaveCriticalSection(&wma->cs);
673
    return 0;
674 675 676
}

/***************************************************************************
677
 * 				MCIAVI_mciResume			[internal]
678
 */
679
static	DWORD	MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
680
{
681
    WINE_MCIAVI *wma;
682

683
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
684

685
    wma = MCIAVI_mciGetOpenDev(wDevID);
686
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
687

688 689
    EnterCriticalSection(&wma->cs);

690 691 692
    if (wma->dwStatus == MCI_MODE_PAUSE)
	wma->dwStatus = MCI_MODE_PLAY;

693 694 695 696
    if (wma->lpWaveFormat) {
    	LeaveCriticalSection(&wma->cs);
	return waveOutRestart(wma->hWave);
    }
697 698

    LeaveCriticalSection(&wma->cs);
699
    return 0;
700 701
}

702 703
/***************************************************************************
 * 				MCIAVI_mciSeek			[internal]
704
 */
705
static	DWORD	MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
706
{
707
    WINE_MCIAVI *wma;
708

709
    TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
710

711 712
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

713
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
714 715

    wma = MCIAVI_mciGetOpenDev(wDevID);
716
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
717

718
    EnterCriticalSection(&wma->cs);
719

720 721 722 723 724
    if (dwFlags & MCI_SEEK_TO_START) {
	wma->dwCurrVideoFrame = 0;
    } else if (dwFlags & MCI_SEEK_TO_END) {
	wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
    } else if (dwFlags & MCI_TO) {
725 726
        if (lpParms->dwTo > wma->dwPlayableVideoFrames - 1)
            lpParms->dwTo = wma->dwPlayableVideoFrames - 1;
727 728 729
	wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
    } else {
	WARN("dwFlag doesn't tell where to seek to...\n");
730
	LeaveCriticalSection(&wma->cs);
731 732
	return MCIERR_MISSING_PARAMETER;
    }
733

734
    TRACE("Seeking to frame=%u bytes\n", wma->dwCurrVideoFrame);
735

736
    if (dwFlags & MCI_NOTIFY) {
737
	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
738
                       wDevID, MCI_NOTIFY_SUCCESSFUL);
739 740
    }
    LeaveCriticalSection(&wma->cs);
741 742 743
    return 0;
}

744 745
/*****************************************************************************
 * 				MCIAVI_mciLoad			[internal]
746
 */
747
static DWORD	MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSW lpParms)
748
{
749
    WINE_MCIAVI *wma;
750

751
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
752

753 754
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

755
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
756 757

    wma = MCIAVI_mciGetOpenDev(wDevID);
758
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
759

760 761 762 763
    return 0;
}

/******************************************************************************
764
 * 				MCIAVI_mciSave			[internal]
765
 */
766
static	DWORD	MCIAVI_mciSave(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SAVE_PARMSW lpParms)
767
{
768
    WINE_MCIAVI *wma;
769

770
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
771

772 773
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

774
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
775 776

    wma = MCIAVI_mciGetOpenDev(wDevID);
777
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
778

779 780 781 782
    return 0;
}

/******************************************************************************
783
 * 				MCIAVI_mciFreeze			[internal]
784
 */
785
static	DWORD	MCIAVI_mciFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
786
{
787
    WINE_MCIAVI *wma;
788

789
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
790

791 792
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

793
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
794 795

    wma = MCIAVI_mciGetOpenDev(wDevID);
796
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
797

798 799 800 801
    return 0;
}

/******************************************************************************
802
 * 				MCIAVI_mciRealize			[internal]
803
 */
804
static	DWORD	MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
805
{
806
    WINE_MCIAVI *wma;
807

808
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
809

810 811
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

812
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
813 814

    wma = MCIAVI_mciGetOpenDev(wDevID);
815
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
816

817 818 819 820
    return 0;
}

/******************************************************************************
821
 * 				MCIAVI_mciUnFreeze			[internal]
822
 */
823
static	DWORD	MCIAVI_mciUnFreeze(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
824
{
825
    WINE_MCIAVI *wma;
826

827
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
828

829 830
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

831
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
832 833

    wma = MCIAVI_mciGetOpenDev(wDevID);
834
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
835

836 837 838 839
    return 0;
}

/******************************************************************************
840
 * 				MCIAVI_mciUpdate			[internal]
841
 */
842
static	DWORD	MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
843
{
844
    WINE_MCIAVI *wma;
845

846
    TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms);
847

848
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
849 850

    wma = MCIAVI_mciGetOpenDev(wDevID);
851
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
852

853 854 855 856 857 858 859
    EnterCriticalSection(&wma->cs);

    if (dwFlags & MCI_DGV_UPDATE_HDC)
        MCIAVI_PaintFrame(wma, lpParms->hDC);

    LeaveCriticalSection(&wma->cs);

860 861 862 863
    return 0;
}

/******************************************************************************
864
 * 				MCIAVI_mciStep			[internal]
865
 */
866
static	DWORD	MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
867
{
868
    WINE_MCIAVI *wma;
869

870
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
871

872 873
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

874
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
875 876

    wma = MCIAVI_mciGetOpenDev(wDevID);
877
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
878

879 880 881 882
    return 0;
}

/******************************************************************************
883
 * 				MCIAVI_mciCopy			[internal]
884
 */
885
static	DWORD	MCIAVI_mciCopy(UINT wDevID, DWORD dwFlags, LPMCI_DGV_COPY_PARMS lpParms)
886
{
887
    WINE_MCIAVI *wma;
888

889
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
890

891 892
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

893
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
894 895

    wma = MCIAVI_mciGetOpenDev(wDevID);
896
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
897

898 899 900 901
    return 0;
}

/******************************************************************************
902
 * 				MCIAVI_mciCut			[internal]
903
 */
904
static	DWORD	MCIAVI_mciCut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUT_PARMS lpParms)
905
{
906
    WINE_MCIAVI *wma;
907

908
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
909

910 911
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

912
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
913 914

    wma = MCIAVI_mciGetOpenDev(wDevID);
915
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
916

917 918 919 920
    return 0;
}

/******************************************************************************
921
 * 				MCIAVI_mciDelete			[internal]
922
 */
923
static	DWORD	MCIAVI_mciDelete(UINT wDevID, DWORD dwFlags, LPMCI_DGV_DELETE_PARMS lpParms)
924
{
925
    WINE_MCIAVI *wma;
926

927
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
928

929 930
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

931
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
932 933

    wma = MCIAVI_mciGetOpenDev(wDevID);
934
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
935

936 937 938 939
    return 0;
}

/******************************************************************************
940
 * 				MCIAVI_mciPaste			[internal]
941
 */
942
static	DWORD	MCIAVI_mciPaste(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PASTE_PARMS lpParms)
943
{
944
    WINE_MCIAVI *wma;
945

946
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
947

948 949
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

950
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
951 952

    wma = MCIAVI_mciGetOpenDev(wDevID);
953
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
954

955 956 957 958
    return 0;
}

/******************************************************************************
959
 * 				MCIAVI_mciCue			[internal]
960
 */
961
static	DWORD	MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
962
{
963
    WINE_MCIAVI *wma;
964

965
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
966

967 968
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

969
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
970 971

    wma = MCIAVI_mciGetOpenDev(wDevID);
972
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
973

974 975 976 977
    return 0;
}

/******************************************************************************
978
 * 				MCIAVI_mciCapture			[internal]
979
 */
980
static	DWORD	MCIAVI_mciCapture(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CAPTURE_PARMSW lpParms)
981
{
982
    WINE_MCIAVI *wma;
983

984
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
985

986 987
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

988
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
989 990

    wma = MCIAVI_mciGetOpenDev(wDevID);
991
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
992

993 994 995
    return 0;
}

996
/******************************************************************************
997
 * 				MCIAVI_mciMonitor			[internal]
998
 */
999
static	DWORD	MCIAVI_mciMonitor(UINT wDevID, DWORD dwFlags, LPMCI_DGV_MONITOR_PARMS lpParms)
1000
{
1001
    WINE_MCIAVI *wma;
1002

1003
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1004

1005 1006
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1007
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1008 1009

    wma = MCIAVI_mciGetOpenDev(wDevID);
1010
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1011

1012 1013 1014 1015
    return 0;
}

/******************************************************************************
1016
 * 				MCIAVI_mciReserve			[internal]
1017
 */
1018
static	DWORD	MCIAVI_mciReserve(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESERVE_PARMSW lpParms)
1019
{
1020
    WINE_MCIAVI *wma;
1021

1022
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1023

1024 1025
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1026
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1027 1028

    wma = MCIAVI_mciGetOpenDev(wDevID);
1029
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1030

1031 1032 1033 1034
    return 0;
}

/******************************************************************************
1035
 * 				MCIAVI_mciSetAudio			[internal]
1036
 */
1037
static	DWORD	MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms)
1038
{
1039
    WINE_MCIAVI *wma;
1040

1041
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1042

1043 1044
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1045
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1046 1047

    wma = MCIAVI_mciGetOpenDev(wDevID);
1048
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1049

1050 1051 1052 1053
    return 0;
}

/******************************************************************************
1054
 * 				MCIAVI_mciSignal			[internal]
1055
 */
1056
static	DWORD	MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
1057
{
1058
    WINE_MCIAVI *wma;
1059

1060
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1061

1062 1063
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1064
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1065 1066

    wma = MCIAVI_mciGetOpenDev(wDevID);
1067
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1068

1069 1070 1071 1072
    return 0;
}

/******************************************************************************
1073
 * 				MCIAVI_mciSetVideo			[internal]
1074
 */
1075
static	DWORD	MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSW lpParms)
1076
{
1077
    WINE_MCIAVI *wma;
1078

1079
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1080

1081 1082
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1083
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1084 1085

    wma = MCIAVI_mciGetOpenDev(wDevID);
1086
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1087

1088 1089 1090 1091
    return 0;
}

/******************************************************************************
1092
 * 				MCIAVI_mciQuality			[internal]
1093
 */
1094
static	DWORD	MCIAVI_mciQuality(UINT wDevID, DWORD dwFlags, LPMCI_DGV_QUALITY_PARMSW lpParms)
1095
{
1096
    WINE_MCIAVI *wma;
1097

1098
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1099

1100 1101
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1102
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1103 1104

    wma = MCIAVI_mciGetOpenDev(wDevID);
1105
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1106

1107 1108 1109 1110
    return 0;
}

/******************************************************************************
1111
 * 				MCIAVI_mciList			[internal]
1112
 */
1113
static	DWORD	MCIAVI_mciList(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LIST_PARMSW lpParms)
1114
{
1115
    WINE_MCIAVI *wma;
1116

1117
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1118

1119 1120
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1121
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1122 1123

    wma = MCIAVI_mciGetOpenDev(wDevID);
1124
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1125

1126 1127 1128 1129
    return 0;
}

/******************************************************************************
1130
 * 				MCIAVI_mciUndo			[internal]
1131
 */
1132
static	DWORD	MCIAVI_mciUndo(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
1133
{
1134
    WINE_MCIAVI *wma;
1135

1136
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1137

1138 1139
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1140
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1141 1142

    wma = MCIAVI_mciGetOpenDev(wDevID);
1143
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1144

1145 1146 1147 1148
    return 0;
}

/******************************************************************************
1149
 * 				MCIAVI_mciConfigure			[internal]
1150
 */
1151
static	DWORD	MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
1152
{
1153
    WINE_MCIAVI *wma;
1154

1155
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1156

1157 1158
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1159
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1160 1161

    wma = MCIAVI_mciGetOpenDev(wDevID);
1162
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1163

1164 1165 1166 1167
    return 0;
}

/******************************************************************************
1168
 * 				MCIAVI_mciRestore			[internal]
1169
 */
1170
static	DWORD	MCIAVI_mciRestore(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RESTORE_PARMSW lpParms)
1171
{
1172
    WINE_MCIAVI *wma;
1173

1174
    FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
1175

1176 1177
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1178
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1179 1180

    wma = MCIAVI_mciGetOpenDev(wDevID);
1181
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1182

1183 1184
    return 0;
}
1185 1186 1187 1188 1189 1190

/*======================================================================*
 *                  	    MCI AVI entry points			*
 *======================================================================*/

/**************************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
1191
 * 				DriverProc (MCIAVI.@)
1192
 */
1193 1194
LRESULT CALLBACK MCIAVI_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
                                   LPARAM dwParam1, LPARAM dwParam2)
1195
{
1196
    TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
1197
	  dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1198

1199 1200 1201
    switch (wMsg) {
    case DRV_LOAD:		return 1;
    case DRV_FREE:		return 1;
1202
    case DRV_OPEN:		return MCIAVI_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2);
1203
    case DRV_CLOSE:		return MCIAVI_drvClose(dwDevID);
1204 1205 1206
    case DRV_ENABLE:		return 1;
    case DRV_DISABLE:		return 1;
    case DRV_QUERYCONFIGURE:	return 1;
1207
    case DRV_CONFIGURE:		return MCIAVI_drvConfigure(dwDevID);
1208 1209
    case DRV_INSTALL:		return DRVCNF_RESTART;
    case DRV_REMOVE:		return DRVCNF_RESTART;
1210
    }
1211

1212 1213
    /* session instance */
    if (dwDevID == 0xFFFFFFFF) return 1;
1214 1215

    switch (wMsg) {
1216
    case MCI_OPEN_DRIVER:	return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW)     dwParam2);
1217 1218 1219 1220 1221 1222 1223
    case MCI_CLOSE_DRIVER:	return MCIAVI_mciClose     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_PLAY:		return MCIAVI_mciPlay      (dwDevID, dwParam1, (LPMCI_PLAY_PARMS)          dwParam2);
    case MCI_RECORD:		return MCIAVI_mciRecord    (dwDevID, dwParam1, (LPMCI_DGV_RECORD_PARMS)    dwParam2);
    case MCI_STOP:		return MCIAVI_mciStop      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_SET:		return MCIAVI_mciSet       (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS)       dwParam2);
    case MCI_PAUSE:		return MCIAVI_mciPause     (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_RESUME:		return MCIAVI_mciResume    (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1224
    case MCI_STATUS:		return MCIAVI_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW)   dwParam2);
1225
    case MCI_GETDEVCAPS:	return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
1226
    case MCI_INFO:		return MCIAVI_mciInfo      (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW)     dwParam2);
1227
    case MCI_SEEK:		return MCIAVI_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
1228
    case MCI_PUT:		return MCIAVI_mciPut	   (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS)       dwParam2);
1229 1230 1231
    case MCI_WINDOW:		return MCIAVI_mciWindow	   (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW)   dwParam2);
    case MCI_LOAD:		return MCIAVI_mciLoad      (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSW)     dwParam2);
    case MCI_SAVE:		return MCIAVI_mciSave      (dwDevID, dwParam1, (LPMCI_DGV_SAVE_PARMSW)     dwParam2);
1232 1233 1234 1235 1236 1237
    case MCI_FREEZE:		return MCIAVI_mciFreeze	   (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
    case MCI_REALIZE:		return MCIAVI_mciRealize   (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_UNFREEZE:		return MCIAVI_mciUnFreeze  (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
    case MCI_UPDATE:		return MCIAVI_mciUpdate    (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)    dwParam2);
    case MCI_WHERE:		return MCIAVI_mciWhere	   (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS)      dwParam2);
    case MCI_STEP:		return MCIAVI_mciStep      (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS)      dwParam2);
1238 1239 1240 1241
    case MCI_COPY:		return MCIAVI_mciCopy      (dwDevID, dwParam1, (LPMCI_DGV_COPY_PARMS)      dwParam2);
    case MCI_CUT:		return MCIAVI_mciCut       (dwDevID, dwParam1, (LPMCI_DGV_CUT_PARMS)       dwParam2);
    case MCI_DELETE:		return MCIAVI_mciDelete    (dwDevID, dwParam1, (LPMCI_DGV_DELETE_PARMS)    dwParam2);
    case MCI_PASTE:		return MCIAVI_mciPaste     (dwDevID, dwParam1, (LPMCI_DGV_PASTE_PARMS)     dwParam2);
1242
    case MCI_CUE:		return MCIAVI_mciCue       (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS)       dwParam2);
1243
	/* Digital Video specific */
1244
    case MCI_CAPTURE:		return MCIAVI_mciCapture   (dwDevID, dwParam1, (LPMCI_DGV_CAPTURE_PARMSW)  dwParam2);
1245
    case MCI_MONITOR:		return MCIAVI_mciMonitor   (dwDevID, dwParam1, (LPMCI_DGV_MONITOR_PARMS)   dwParam2);
1246 1247
    case MCI_RESERVE:		return MCIAVI_mciReserve   (dwDevID, dwParam1, (LPMCI_DGV_RESERVE_PARMSW)  dwParam2);
    case MCI_SETAUDIO:		return MCIAVI_mciSetAudio  (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
1248
    case MCI_SIGNAL:		return MCIAVI_mciSignal    (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS)    dwParam2);
1249 1250 1251
    case MCI_SETVIDEO:		return MCIAVI_mciSetVideo  (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSW) dwParam2);
    case MCI_QUALITY:		return MCIAVI_mciQuality   (dwDevID, dwParam1, (LPMCI_DGV_QUALITY_PARMSW)  dwParam2);
    case MCI_LIST:		return MCIAVI_mciList      (dwDevID, dwParam1, (LPMCI_DGV_LIST_PARMSW)     dwParam2);
1252 1253
    case MCI_UNDO:		return MCIAVI_mciUndo      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_CONFIGURE:		return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1254
    case MCI_RESTORE:		return MCIAVI_mciRestore   (dwDevID, dwParam1, (LPMCI_DGV_RESTORE_PARMSW)  dwParam2);
1255

1256
    case MCI_SPIN:
1257
    case MCI_ESCAPE:
1258
	WARN("Unsupported command [%u]\n", wMsg);
1259 1260 1261
	break;
    case MCI_OPEN:
    case MCI_CLOSE:
1262
	FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1263
	break;
1264
    default:
1265
	TRACE("Sending msg [%u] to default driver proc\n", wMsg);
1266
	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1267 1268 1269
    }
    return MCIERR_UNRECOGNIZED_COMMAND;
}