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->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs");
88
    wma->ack_event = CreateEventW(NULL, FALSE, FALSE, NULL);
89
    wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
90
    wma->wDevID = modp->wDeviceID;
91 92
    wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
    modp->wCustomCommandTable = wma->wCommandTable;
93
    modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
94
    mciSetDriverData(wma->wDevID, (DWORD_PTR)wma);
95

96
    return modp->wDeviceID;
97 98 99
}

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

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

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

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

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

116 117
        EnterCriticalSection(&wma->cs);

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

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

124
        LeaveCriticalSection(&wma->cs);
125
        wma->cs.DebugInfo->Spare[0] = 0;
126 127
        DeleteCriticalSection(&wma->cs);

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

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

141
    TRACE("%04x\n", dwDevID);
142 143 144 145

    MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);

    wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
146 147

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

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

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

168 169 170 171 172 173 174
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;
175

176
        HeapFree(GetProcessHeap(), 0, wma->lpFileName);
177 178
        wma->lpFileName = NULL;

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

198
        HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
199 200 201 202 203 204
	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;
205
        wma->dwCachedFrame = -1;
206 207 208
    }
}

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

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

220 221
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

222
    if (lpOpenParms == NULL) 		return MCIERR_NULL_PARAMETER_BLOCK;
223 224

    wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
225
    if (wma == NULL)			return MCIERR_INVALID_DEVICE_ID;
226

227 228
    EnterCriticalSection(&wma->cs);

229 230 231 232 233 234 235
    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
236 237
        {
            LeaveCriticalSection(&wma->cs);
238
	    return MCIERR_MUST_USE_SHAREABLE;
239
        }
240 241 242 243
    } else {
	wma->nUseCount = 1;
	wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
    }
244 245 246

    wma->dwStatus = MCI_MODE_NOT_READY;

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

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

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

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

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

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

292 293
    LeaveCriticalSection(&wma->cs);
    return dwRet;
294 295
}

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

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

306 307
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

308
    wma = MCIAVI_mciGetOpenDev(wDevID);
309
    if (wma == NULL) 	return MCIERR_INVALID_DEVICE_ID;
310

311 312
    EnterCriticalSection(&wma->cs);

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

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

    LeaveCriticalSection(&wma->cs);
329
    return dwRet;
330 331
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
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;

352
    TRACE("In thread before async play command (id %08x, flags %08x)\n", data->wDevID, data->flags);
353
    ret = MCIAVI_mciPlay(data->wDevID, data->flags | MCI_WAIT, &data->params);
354
    TRACE("In thread after async play command (id %08x, flags %08x)\n", data->wDevID, data->flags);
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

    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;
372
    data->params = *lpParams;
373 374 375 376 377 378 379 380 381 382 383 384 385 386

    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;
}

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

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

403
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
404

405
    wma = MCIAVI_mciGetOpenDev(wDevID);
406
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
407

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

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

421
    LeaveCriticalSection(&wma->cs);
422

423 424
    if (!(dwFlags & MCI_WAIT))
        return MCIAVI_mciPlay_async(wma, dwFlags, lpParms);
425

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

    EnterCriticalSection(&wma->cs);
430

431 432
    dwFromFrame = wma->dwCurrVideoFrame;
    dwToFrame = wma->dwPlayableVideoFrames - 1;
433

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

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

445
    wma->dwCurrVideoFrame = dwFromFrame;
446
    wma->dwToVideoFrame = dwToFrame;
447

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

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

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

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

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

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

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

490
	tc = GetTickCount();
491

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

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

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

505 506
	    MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
	    delta = GetTickCount() - tc;
507 508

            LeaveCriticalSection(&wma->cs);
509
            ret = WaitForMultipleObjects(2, events, FALSE, (delta >= frameTime) ? 0 : frameTime - delta);
510 511
            EnterCriticalSection(&wma->cs);

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

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

521
        LeaveCriticalSection(&wma->cs);
522
        ret = WaitForMultipleObjects(1, &wma->hStopEvent, FALSE, delta);
523 524
        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;
}