mciavi.c 38.6 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 308
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

    wma = (WINE_MCIAVI *)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 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386

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

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 = (WINE_MCIAVI *)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 510
            ret = MsgWaitForMultipleObjectsEx(2, events,
                (delta >= frameTime) ? 0 : frameTime - delta, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
511 512
            EnterCriticalSection(&wma->cs);

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

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

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

       if (wma->dwCurrVideoFrame < dwToFrame)
           wma->dwCurrVideoFrame++;
        else
            break;
532
    }
533 534

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

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

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

551
    dwRet = 0;
552

553 554
    if (wma->lpWaveFormat) {
	HeapFree(GetProcessHeap(), 0, waveHdr);
555

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

565 566 567
mci_play_done:
    wma->dwStatus = MCI_MODE_STOP;

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

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

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

586 587
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

588
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
589 590

    wma = MCIAVI_mciGetOpenDev(wDevID);
591
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
592

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

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

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

609
    wma = MCIAVI_mciGetOpenDev(wDevID);
610
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
611

612 613
    EnterCriticalSection(&wma->cs);

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

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

638
	break;
639 640 641

    case MCI_MODE_NOT_READY:
        break;        
642
    }
643

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

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

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

661
    wma = MCIAVI_mciGetOpenDev(wDevID);
662
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
663

664 665
    EnterCriticalSection(&wma->cs);

666 667 668
    if (wma->dwStatus == MCI_MODE_PLAY)
	wma->dwStatus = MCI_MODE_PAUSE;

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

674
    LeaveCriticalSection(&wma->cs);
675
    return 0;
676 677 678
}

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

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

687
    wma = MCIAVI_mciGetOpenDev(wDevID);
688
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
689

690 691
    EnterCriticalSection(&wma->cs);

692 693 694
    if (wma->dwStatus == MCI_MODE_PAUSE)
	wma->dwStatus = MCI_MODE_PLAY;

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

    LeaveCriticalSection(&wma->cs);
701
    return 0;
702 703
}

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

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

713 714
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

715
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
716 717

    wma = MCIAVI_mciGetOpenDev(wDevID);
718
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
719

720
    EnterCriticalSection(&wma->cs);
721

722 723 724 725 726
    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) {
727 728
        if (lpParms->dwTo > wma->dwPlayableVideoFrames - 1)
            lpParms->dwTo = wma->dwPlayableVideoFrames - 1;
729 730 731
	wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
    } else {
	WARN("dwFlag doesn't tell where to seek to...\n");
732
	LeaveCriticalSection(&wma->cs);
733 734
	return MCIERR_MISSING_PARAMETER;
    }
735

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

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

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

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

755 756
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

757
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
758 759

    wma = MCIAVI_mciGetOpenDev(wDevID);
760
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
761

762 763 764 765
    return 0;
}

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

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

774 775
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

776
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
777 778

    wma = MCIAVI_mciGetOpenDev(wDevID);
779
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
780

781 782 783 784
    return 0;
}

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

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

793 794
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

795
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
796 797

    wma = MCIAVI_mciGetOpenDev(wDevID);
798
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
799

800 801 802 803
    return 0;
}

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

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

812 813
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

814
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
815 816

    wma = MCIAVI_mciGetOpenDev(wDevID);
817
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
818

819 820 821 822
    return 0;
}

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

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

831 832
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

833
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
834 835

    wma = MCIAVI_mciGetOpenDev(wDevID);
836
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
837

838 839 840 841
    return 0;
}

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

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

850
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
851 852

    wma = MCIAVI_mciGetOpenDev(wDevID);
853
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
854

855 856 857 858 859 860 861
    EnterCriticalSection(&wma->cs);

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

    LeaveCriticalSection(&wma->cs);

862 863 864 865
    return 0;
}

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

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

874 875
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

876
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
877 878

    wma = MCIAVI_mciGetOpenDev(wDevID);
879
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
880

881 882 883 884
    return 0;
}

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

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

893 894
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

895
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
896 897

    wma = MCIAVI_mciGetOpenDev(wDevID);
898
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
899

900 901 902 903
    return 0;
}

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

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

912 913
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

914
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
915 916

    wma = MCIAVI_mciGetOpenDev(wDevID);
917
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
918

919 920 921 922
    return 0;
}

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

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

931 932
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

933
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
934 935

    wma = MCIAVI_mciGetOpenDev(wDevID);
936
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
937

938 939 940 941
    return 0;
}

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

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

950 951
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

952
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
953 954

    wma = MCIAVI_mciGetOpenDev(wDevID);
955
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
956

957 958 959 960
    return 0;
}

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

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

969 970
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

971
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
972 973

    wma = MCIAVI_mciGetOpenDev(wDevID);
974
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
975

976 977 978 979
    return 0;
}

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

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

988 989
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

990
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
991 992

    wma = MCIAVI_mciGetOpenDev(wDevID);
993
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
994

995 996 997
    return 0;
}

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

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

1007 1008
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1009
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1010 1011

    wma = MCIAVI_mciGetOpenDev(wDevID);
1012
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1013

1014 1015 1016 1017
    return 0;
}

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

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

1026 1027
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1028
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1029 1030

    wma = MCIAVI_mciGetOpenDev(wDevID);
1031
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1032

1033 1034 1035 1036
    return 0;
}

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

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

1045 1046
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1047
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1048 1049

    wma = MCIAVI_mciGetOpenDev(wDevID);
1050
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1051

1052 1053 1054 1055
    return 0;
}

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

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

1064 1065
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1066
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1067 1068

    wma = MCIAVI_mciGetOpenDev(wDevID);
1069
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1070

1071 1072 1073 1074
    return 0;
}

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

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

1083 1084
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1085
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1086 1087

    wma = MCIAVI_mciGetOpenDev(wDevID);
1088
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1089

1090 1091 1092 1093
    return 0;
}

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

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

1102 1103
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1104
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1105 1106

    wma = MCIAVI_mciGetOpenDev(wDevID);
1107
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1108

1109 1110 1111 1112
    return 0;
}

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

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

1121 1122
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1123
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1124 1125

    wma = MCIAVI_mciGetOpenDev(wDevID);
1126
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1127

1128 1129 1130 1131
    return 0;
}

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

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

1140 1141
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1142
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1143 1144

    wma = MCIAVI_mciGetOpenDev(wDevID);
1145
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1146

1147 1148 1149 1150
    return 0;
}

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

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

1159 1160
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1161
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1162 1163

    wma = MCIAVI_mciGetOpenDev(wDevID);
1164
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1165

1166 1167 1168 1169
    return 0;
}

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

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

1178 1179
    MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);

1180
    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;
1181 1182

    wma = MCIAVI_mciGetOpenDev(wDevID);
1183
    if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
1184

1185 1186
    return 0;
}
1187 1188 1189 1190 1191 1192

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

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

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

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

    switch (wMsg) {
1218
    case MCI_OPEN_DRIVER:	return MCIAVI_mciOpen      (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW)     dwParam2);
1219 1220 1221 1222 1223 1224 1225
    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);
1226
    case MCI_STATUS:		return MCIAVI_mciStatus    (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW)   dwParam2);
1227
    case MCI_GETDEVCAPS:	return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)    dwParam2);
1228
    case MCI_INFO:		return MCIAVI_mciInfo      (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW)     dwParam2);
1229
    case MCI_SEEK:		return MCIAVI_mciSeek      (dwDevID, dwParam1, (LPMCI_SEEK_PARMS)          dwParam2);
1230
    case MCI_PUT:		return MCIAVI_mciPut	   (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS)       dwParam2);
1231 1232 1233
    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);
1234 1235 1236 1237 1238 1239
    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);
1240 1241 1242 1243
    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);
1244
    case MCI_CUE:		return MCIAVI_mciCue       (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS)       dwParam2);
1245
	/* Digital Video specific */
1246
    case MCI_CAPTURE:		return MCIAVI_mciCapture   (dwDevID, dwParam1, (LPMCI_DGV_CAPTURE_PARMSW)  dwParam2);
1247
    case MCI_MONITOR:		return MCIAVI_mciMonitor   (dwDevID, dwParam1, (LPMCI_DGV_MONITOR_PARMS)   dwParam2);
1248 1249
    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);
1250
    case MCI_SIGNAL:		return MCIAVI_mciSignal    (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS)    dwParam2);
1251 1252 1253
    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);
1254 1255
    case MCI_UNDO:		return MCIAVI_mciUndo      (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
    case MCI_CONFIGURE:		return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)       dwParam2);
1256
    case MCI_RESTORE:		return MCIAVI_mciRestore   (dwDevID, dwParam1, (LPMCI_DGV_RESTORE_PARMSW)  dwParam2);
1257

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