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) ...@@ -152,6 +152,7 @@ static DWORD MCIAVI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
return 0; return 0;
InitializeCriticalSection(&wma->cs); InitializeCriticalSection(&wma->cs);
wma->hStopEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
wma->wDevID = modp->wDeviceID; wma->wDevID = modp->wDeviceID;
wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0); wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
modp->wCustomCommandTable = wma->wCommandTable; modp->wCustomCommandTable = wma->wCommandTable;
...@@ -183,6 +184,8 @@ static DWORD MCIAVI_drvClose(DWORD dwDevID) ...@@ -183,6 +184,8 @@ static DWORD MCIAVI_drvClose(DWORD dwDevID)
mciSetDriverData(dwDevID, 0); mciSetDriverData(dwDevID, 0);
mciFreeCommandResource(wma->wCommandTable); mciFreeCommandResource(wma->wCommandTable);
CloseHandle(wma->hStopEvent);
LeaveCriticalSection(&wma->cs); LeaveCriticalSection(&wma->cs);
DeleteCriticalSection(&wma->cs); DeleteCriticalSection(&wma->cs);
...@@ -263,6 +266,7 @@ static void MCIAVI_CleanUp(WINE_MCIAVI* wma) ...@@ -263,6 +266,7 @@ static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
memset(&wma->ash_video, 0, sizeof(wma->ash_video)); memset(&wma->ash_video, 0, sizeof(wma->ash_video));
memset(&wma->ash_audio, 0, sizeof(wma->ash_audio)); memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0; wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
wma->dwCachedFrame = -1;
} }
} }
...@@ -477,28 +481,44 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms ...@@ -477,28 +481,44 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms
while (wma->dwStatus == MCI_MODE_PLAY) while (wma->dwStatus == MCI_MODE_PLAY)
{ {
HDC hDC;
tc = GetTickCount(); 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) { if (wma->lpWaveFormat) {
HANDLE events[2];
DWORD ret;
events[0] = wma->hStopEvent;
events[1] = wma->hEvent;
MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr); MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
delta = GetTickCount() - tc; delta = GetTickCount() - tc;
LeaveCriticalSection(&wma->cs); LeaveCriticalSection(&wma->cs);
MsgWaitForMultipleObjects(1, &wma->hEvent, FALSE, ret = MsgWaitForMultipleObjects(2, events, FALSE,
(delta >= frameTime) ? 0 : frameTime - delta, MWMO_INPUTAVAILABLE); (delta >= frameTime) ? 0 : frameTime - delta, MWMO_INPUTAVAILABLE);
EnterCriticalSection(&wma->cs); EnterCriticalSection(&wma->cs);
if (wma->dwStatus != MCI_MODE_PLAY) break; if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
} }
delta = GetTickCount() - tc; delta = GetTickCount() - tc;
if (delta < frameTime) if (delta < frameTime)
{ {
DWORD ret;
LeaveCriticalSection(&wma->cs); LeaveCriticalSection(&wma->cs);
MsgWaitForMultipleObjects(0, NULL, FALSE, frameTime - delta, MWMO_INPUTAVAILABLE); ret = MsgWaitForMultipleObjects(1, &wma->hStopEvent, FALSE, frameTime - delta, MWMO_INPUTAVAILABLE);
EnterCriticalSection(&wma->cs); EnterCriticalSection(&wma->cs);
if (ret == WAIT_OBJECT_0) break;
} }
if (wma->dwCurrVideoFrame < dwToFrame) if (wma->dwCurrVideoFrame < dwToFrame)
...@@ -584,21 +604,18 @@ static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa ...@@ -584,21 +604,18 @@ static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpPa
EnterCriticalSection(&wma->cs); EnterCriticalSection(&wma->cs);
switch (wma->dwStatus) { switch (wma->dwStatus) {
case MCI_MODE_PAUSE:
case MCI_MODE_PLAY: case MCI_MODE_PLAY:
case MCI_MODE_RECORD: case MCI_MODE_RECORD:
{ SetEvent(wma->hStopEvent);
int oldStat = wma->dwStatus; /* fall through */
wma->dwStatus = MCI_MODE_NOT_READY; case MCI_MODE_PAUSE:
if (oldStat == MCI_MODE_PAUSE) dwRet = waveOutReset(wma->hWave);
dwRet = waveOutReset(wma->hWave); /* fall through */
}
/* fall through */
default: default:
do /* one more chance for an async thread to finish */ do /* one more chance for an async thread to finish */
{ {
LeaveCriticalSection(&wma->cs); LeaveCriticalSection(&wma->cs);
Sleep(10); Sleep(10);
EnterCriticalSection(&wma->cs); EnterCriticalSection(&wma->cs);
} while (wma->dwStatus != MCI_MODE_STOP); } while (wma->dwStatus != MCI_MODE_STOP);
...@@ -685,6 +702,8 @@ static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms ...@@ -685,6 +702,8 @@ static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms
} else if (dwFlags & MCI_SEEK_TO_END) { } else if (dwFlags & MCI_SEEK_TO_END) {
wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1; wma->dwCurrVideoFrame = wma->dwPlayableVideoFrames - 1;
} else if (dwFlags & MCI_TO) { } else if (dwFlags & MCI_TO) {
if (lpParms->dwTo > wma->dwPlayableVideoFrames - 1)
lpParms->dwTo = wma->dwPlayableVideoFrames - 1;
wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); wma->dwCurrVideoFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
} else { } else {
WARN("dwFlag doesn't tell where to seek to...\n"); 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 ...@@ -804,15 +823,20 @@ static DWORD MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS
{ {
WINE_MCIAVI *wma; WINE_MCIAVI *wma;
FIXME("(%04x, %08lx, %p) : stub\n", wDevID, dwFlags, lpParms); TRACE("%04x, %08lx, %p\n", wDevID, dwFlags, lpParms);
MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
wma = MCIAVI_mciGetOpenDev(wDevID); wma = MCIAVI_mciGetOpenDev(wDevID);
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 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; return 0;
} }
......
...@@ -406,20 +406,22 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) ...@@ -406,20 +406,22 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma) BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
{ {
HDC hDC;
DWORD outSize; DWORD outSize;
FOURCC fcc = wma->ash_video.fccHandler; FOURCC fcc = wma->ash_video.fccHandler;
TRACE("fcc %4.4s\n", (LPSTR)&fcc); TRACE("fcc %4.4s\n", (LPSTR)&fcc);
wma->dwCachedFrame = -1;
/* check for builtin DIB compressions */ /* check for builtin DIB compressions */
if ((fcc == mmioFOURCC('D','I','B',' ')) || if ((fcc == mmioFOURCC('D','I','B',' ')) ||
(fcc == mmioFOURCC('R','L','E',' ')) || (fcc == mmioFOURCC('R','L','E',' ')) ||
(fcc == BI_RGB) || (fcc == BI_RLE8) || (fcc == BI_RGB) || (fcc == BI_RLE8) ||
(fcc == BI_RLE4) || (fcc == BI_BITFIELDS)) (fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
{ {
wma->hic = 0; wma->hic = 0;
MCIAVI_DrawFrame(wma); goto paint_frame;
return TRUE;
} }
/* get the right handle */ /* get the right handle */
...@@ -469,8 +471,13 @@ BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma) ...@@ -469,8 +471,13 @@ BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
return FALSE; 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; return TRUE;
} }
...@@ -590,7 +597,31 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) ...@@ -590,7 +597,31 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
if (!hDC || !wma->inbih) if (!hDC || !wma->inbih)
return TRUE; 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) { if (wma->hic) {
pBitmapData = wma->outdata; pBitmapData = wma->outdata;
...@@ -624,34 +655,3 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) ...@@ -624,34 +655,3 @@ LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
DeleteDC(hdcMem); DeleteDC(hdcMem);
return TRUE; 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 { ...@@ -74,11 +74,13 @@ typedef struct {
DWORD dwEventCount; /* for synchronization */ DWORD dwEventCount; /* for synchronization */
/* data for play back */ /* data for play back */
HWND hWnd, hWndPaint; HWND hWnd, hWndPaint;
DWORD dwCachedFrame; /* buffered frame */
DWORD dwCurrVideoFrame; /* video frame to display and current position */ DWORD dwCurrVideoFrame; /* video frame to display and current position */
DWORD dwCurrAudioBlock; /* current audio block being played */ DWORD dwCurrAudioBlock; /* current audio block being played */
RECT source, dest; RECT source, dest;
/* data for the background mechanism */ /* data for the background mechanism */
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
HANDLE hStopEvent;
} WINE_MCIAVI; } WINE_MCIAVI;
extern HINSTANCE MCIAVI_hInstance; extern HINSTANCE MCIAVI_hInstance;
...@@ -96,7 +98,6 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma); ...@@ -96,7 +98,6 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma);
DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr); DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr);
BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma); BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma);
void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr); void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr);
LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma);
LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC); LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC);
/* mciavi.c */ /* mciavi.c */
......
...@@ -73,8 +73,8 @@ static LRESULT WINAPI MCIAVI_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPA ...@@ -73,8 +73,8 @@ static LRESULT WINAPI MCIAVI_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPA
else else
{ {
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps); BeginPaint(hWnd, &ps);
MCIAVI_PaintFrame(wma, hDC); MCIAVI_PaintFrame(wma, ps.hdc);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
} }
...@@ -261,12 +261,11 @@ DWORD MCIAVI_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSA lpPar ...@@ -261,12 +261,11 @@ DWORD MCIAVI_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSA lpPar
TRACE("Setting hWnd to %p\n", lpParms->hWnd); TRACE("Setting hWnd to %p\n", lpParms->hWnd);
if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE); if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE);
wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd; wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd;
InvalidateRect(wma->hWndPaint, NULL, FALSE);
} }
} }
if (dwFlags & MCI_DGV_WINDOW_STATE) { if (dwFlags & MCI_DGV_WINDOW_STATE) {
TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow); TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow);
ShowWindow(wma->hWndPaint, lpParms->nCmdShow); ShowWindow(wma->hWndPaint, lpParms->nCmdShow);
} }
if (dwFlags & MCI_DGV_WINDOW_TEXT) { if (dwFlags & MCI_DGV_WINDOW_TEXT) {
TRACE("Setting caption to '%s'\n", lpParms->lpstrText); 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