Commit 19924767 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

- Add a lot of traces to make debugging a bit easier.

- Add support for MCIWNDF_NOAUTOSIZEMOVIE, MCIWNDF_NOAUTOSIZEWINDOW and MCIWNDF_NOERRORDLG flags in the MCIWndClass implementation. - Implement support for MCI_UPDATE in the MCIAVI driver and use it in the MCIWndClass WM_PAINT handler. - Reimplement MCI_STOP command in the MCIAVI driver via an event. - Add a test preventing the MCIAVI driver to crash after MCI_SEEK behind an end of stream.
parent e9ed2f31
......@@ -152,6 +152,7 @@ static DWORD MCIAVI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
return 0;
InitializeCriticalSection(&wma->cs);
wma->hStopEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
wma->wDevID = modp->wDeviceID;
wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
modp->wCustomCommandTable = wma->wCommandTable;
......@@ -183,6 +184,8 @@ static DWORD MCIAVI_drvClose(DWORD dwDevID)
mciSetDriverData(dwDevID, 0);
mciFreeCommandResource(wma->wCommandTable);
CloseHandle(wma->hStopEvent);
LeaveCriticalSection(&wma->cs);
DeleteCriticalSection(&wma->cs);
......@@ -263,6 +266,7 @@ static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
memset(&wma->ash_video, 0, sizeof(wma->ash_video));
memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
wma->dwCachedFrame = -1;
}
}
......@@ -477,28 +481,44 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
while (wma->dwStatus == MCI_MODE_PLAY)
{
HDC hDC;
tc = GetTickCount();
MCIAVI_DrawFrame(wma);
hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
if (hDC)
{
MCIAVI_PaintFrame(wma, hDC);
ReleaseDC(wma->hWndPaint, hDC);
}
if (wma->lpWaveFormat) {
HANDLE events[2];
DWORD ret;
events[0] = wma->hStopEvent;
events[1] = wma->hEvent;
MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
delta = GetTickCount() - tc;
LeaveCriticalSection(&wma->cs);
MsgWaitForMultipleObjects(1, &wma->hEvent, FALSE,
ret = MsgWaitForMultipleObjects(2, events, FALSE,
(delta >= frameTime) ? 0 : frameTime - delta, MWMO_INPUTAVAILABLE);
EnterCriticalSection(&wma->cs);
if (wma->dwStatus != MCI_MODE_PLAY) break;
if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
}
delta = GetTickCount() - tc;
if (delta < frameTime)
{
DWORD ret;
LeaveCriticalSection(&wma->cs);
MsgWaitForMultipleObjects(0, NULL, FALSE, frameTime - delta, MWMO_INPUTAVAILABLE);
ret = MsgWaitForMultipleObjects(1, &wma->hStopEvent, FALSE, frameTime - delta, MWMO_INPUTAVAILABLE);
EnterCriticalSection(&wma->cs);
if (ret == WAIT_OBJECT_0) break;
}
if (wma->dwCurrVideoFrame < dwToFrame)
......@@ -584,21 +604,18 @@ static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa
EnterCriticalSection(&wma->cs);
switch (wma->dwStatus) {
case MCI_MODE_PAUSE:
case MCI_MODE_PLAY:
case MCI_MODE_RECORD:
{
int oldStat = wma->dwStatus;
wma->dwStatus = MCI_MODE_NOT_READY;
if (oldStat == MCI_MODE_PAUSE)
dwRet = waveOutReset(wma->hWave);
}
/* fall through */
SetEvent(wma->hStopEvent);
/* fall through */
case MCI_MODE_PAUSE:
dwRet = waveOutReset(wma->hWave);
/* fall through */
default:
do /* one more chance for an async thread to finish */
{
LeaveCriticalSection(&wma->cs);
Sleep(10);
Sleep(10);
EnterCriticalSection(&wma->cs);
} while (wma->dwStatus != MCI_MODE_STOP);
......@@ -685,6 +702,8 @@ static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
} else if (dwFlags & MCI_SEEK_TO_END) {
wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
} else if (dwFlags & MCI_TO) {
if (lpParms->dwTo > wma->dwPlayableVideoFrames - 1)
lpParms->dwTo = wma->dwPlayableVideoFrames - 1;
wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
} else {
WARN("dwFlag doesn't tell where to seek to...\n");
......@@ -804,15 +823,20 @@ static DWORD MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS
{
WINE_MCIAVI *wma;
FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms);
MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
TRACE("%04x, %08lx, %p\n", wDevID, dwFlags, lpParms);
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
wma = MCIAVI_mciGetOpenDev(wDevID);
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
EnterCriticalSection(&wma->cs);
if (dwFlags & MCI_DGV_UPDATE_HDC)
MCIAVI_PaintFrame(wma, lpParms->hDC);
LeaveCriticalSection(&wma->cs);
return 0;
}
......
......@@ -406,20 +406,22 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
{
HDC hDC;
DWORD outSize;
FOURCC fcc = wma->ash_video.fccHandler;
TRACE("fcc %4.4s\n", (LPSTR)&fcc);
wma->dwCachedFrame = -1;
/* check for builtin DIB compressions */
if ((fcc == mmioFOURCC('D','I','B',' ')) ||
(fcc == mmioFOURCC('R','L','E',' ')) ||
(fcc == mmioFOURCC('R','L','E',' ')) ||
(fcc == BI_RGB) || (fcc == BI_RLE8) ||
(fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
{
wma->hic = 0;
MCIAVI_DrawFrame(wma);
return TRUE;
goto paint_frame;
}
/* get the right handle */
......@@ -469,8 +471,13 @@ BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
return FALSE;
}
MCIAVI_DrawFrame(wma);
paint_frame:
hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
if (hDC)
{
MCIAVI_PaintFrame(wma, hDC);
ReleaseDC(wma->hWndPaint, hDC);
}
return TRUE;
}
......@@ -590,7 +597,31 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
if (!hDC || !wma->inbih)
return TRUE;
TRACE("Painting frame %lu\n", wma->dwCurrVideoFrame);
TRACE("Painting frame %lu (cached %lu)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame);
if (wma->dwCurrVideoFrame != wma->dwCachedFrame)
{
if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
return FALSE;
if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize)
{
mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
/* FIXME ? */
wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
wma->outbih, wma->outdata) != ICERR_OK)
{
WARN("Decompression error\n");
return FALSE;
}
}
wma->dwCachedFrame = wma->dwCurrVideoFrame;
}
if (wma->hic) {
pBitmapData = wma->outdata;
......@@ -624,34 +655,3 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
DeleteDC(hdcMem);
return TRUE;
}
LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma)
{
HDC hDC;
TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame);
if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset ||
!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize)
return FALSE;
mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
/* FIXME ? */
wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
if (wma->hic &&
ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
wma->outbih, wma->outdata) != ICERR_OK) {
WARN("Decompression error\n");
return FALSE;
}
if (IsWindowVisible(wma->hWndPaint) && (hDC = GetDC(wma->hWndPaint)) != 0) {
MCIAVI_PaintFrame(wma, hDC);
ReleaseDC(wma->hWndPaint, hDC);
}
return TRUE;
}
......@@ -74,11 +74,13 @@ typedef struct {
DWORD dwEventCount; /* for synchronization */
/* data for play back */
HWND hWnd, hWndPaint;
DWORD dwCachedFrame; /* buffered frame */
DWORD dwCurrVideoFrame; /* video frame to display and current position */
DWORD dwCurrAudioBlock; /* current audio block being played */
RECT source, dest;
/* data for the background mechanism */
CRITICAL_SECTION cs;
HANDLE hStopEvent;
} WINE_MCIAVI;
extern HINSTANCE MCIAVI_hInstance;
......@@ -96,7 +98,6 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma);
DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr);
BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma);
void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr);
LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma);
LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC);
/* mciavi.c */
......
......@@ -73,8 +73,8 @@ static LRESULT WINAPI MCIAVI_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPA
else
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
MCIAVI_PaintFrame(wma, hDC);
BeginPaint(hWnd, &ps);
MCIAVI_PaintFrame(wma, ps.hdc);
EndPaint(hWnd, &ps);
}
......@@ -261,12 +261,11 @@ DWORD MCIAVI_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSA lpPar
TRACE("Setting hWnd to %p\n", lpParms->hWnd);
if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE);
wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd;
InvalidateRect(wma->hWndPaint, NULL, FALSE);
}
}
if (dwFlags & MCI_DGV_WINDOW_STATE) {
TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow);
ShowWindow(wma->hWndPaint, lpParms->nCmdShow);
ShowWindow(wma->hWndPaint, lpParms->nCmdShow);
}
if (dwFlags & MCI_DGV_WINDOW_TEXT) {
TRACE("Setting caption to '%s'\n", lpParms->lpstrText);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment