Various AVI file playback improvements

Dmitry Timoshkov dmitry at baikal.ru
Sat Feb 28 10:28:59 CST 2004


Hello,

Alexandre,
please let me know if I have to break this patch into smaller parts.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    - 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.

diff -u cvs/hq/wine/dlls/msvideo/mciwnd.c wine/dlls/msvideo/mciwnd.c
--- cvs/hq/wine/dlls/msvideo/mciwnd.c	2004-02-28 12:12:25.000000000 +0800
+++ wine/dlls/msvideo/mciwnd.c	2004-02-29 00:09:14.000000000 +0800
@@ -18,7 +18,7 @@
  *
  * FIXME:
  * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
- * Add support for all MCIWNDF_ flags.
+ * Add support for MCIWNDF_RECORD.
  */
 
 #include <stdarg.h>
@@ -197,6 +197,9 @@ static void MCIWND_UpdateState(MCIWndInf
     if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
         SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
 
+    if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
+        return;
+
     if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
         strcpyW(buffer, mwi->lpName);
     else
@@ -458,11 +461,15 @@ static LRESULT WINAPI MCIWndProc(HWND hW
 
     case WM_PAINT:
         {
-            HDC hdc;
+            MCI_DGV_UPDATE_PARMS mci_update;
             PAINTSTRUCT ps;
 
-            hdc = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
-            /* something to do ? */
+            mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
+
+            mciSendCommandW(mwi->mci, MCI_UPDATE,
+                            MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT,
+                            (DWORD_PTR)&mci_update);
+
             if (!wParam) EndPaint(hWnd, &ps);
             return 1;
         }
@@ -487,6 +494,17 @@ static LRESULT WINAPI MCIWndProc(HWND hW
         SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
         SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
 
+        if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE))
+        {
+            RECT rc;
+
+            rc.left = rc.top = 0;
+            rc.right = LOWORD(lParam);
+            rc.bottom = HIWORD(lParam);
+            if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
+                rc.bottom -= 32; /* subtract the height of the playbar */
+            SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
+        }
         MCIWND_notify_size(mwi);
         break;
 
@@ -540,7 +558,7 @@ static LRESULT WINAPI MCIWndProc(HWND hW
                                              (DWORD_PTR)&mci_open);
             SetCursor(hCursor);
 
-            if (mwi->lasterror)
+            if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG))
             {
                 /* FIXME: get the caption from resources */
                 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
@@ -628,9 +646,11 @@ end_of_mci_open:
         }
 
     case MCIWNDM_GETDEVICEID:
+        TRACE("MCIWNDM_GETDEVICEID\n");
         return mwi->mci;
 
     case MCIWNDM_GETALIAS:
+        TRACE("MCIWNDM_GETALIAS\n");
         return mwi->alias;
 
     case MCIWNDM_GET_SOURCE:
@@ -646,6 +666,7 @@ end_of_mci_open:
                 return mwi->lasterror;
             }
             *(RECT *)lParam = mci_rect.rc;
+            TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc));
             return 0;
         }
 
@@ -662,6 +683,7 @@ end_of_mci_open:
                 return mwi->lasterror;
             }
             *(RECT *)lParam = mci_rect.rc;
+            TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc));
             return 0;
         }
 
@@ -670,6 +692,7 @@ end_of_mci_open:
             MCI_DGV_PUT_PARMS mci_put;
 
             mci_put.rc = *(RECT *)lParam;
+            TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc));
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
                                              MCI_DGV_PUT_SOURCE,
                                              (DWORD_PTR)&mci_put);
@@ -686,6 +709,8 @@ end_of_mci_open:
             MCI_DGV_PUT_PARMS mci_put;
 
             mci_put.rc = *(RECT *)lParam;
+            TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc));
+
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
                                              MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
                                              (DWORD_PTR)&mci_put);
@@ -710,6 +735,7 @@ end_of_mci_open:
                 MCIWND_notify_error(mwi);
                 return 0;
             }
+            TRACE("MCIWNDM_GETLENGTH: %ld\n", mci_status.dwReturn);
             return mci_status.dwReturn;
         }
 
@@ -726,6 +752,7 @@ end_of_mci_open:
                 MCIWND_notify_error(mwi);
                 return 0;
             }
+            TRACE("MCIWNDM_GETSTART: %ld\n", mci_status.dwReturn);
             return mci_status.dwReturn;
         }
 
@@ -735,6 +762,7 @@ end_of_mci_open:
 
             start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
             length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
+            TRACE("MCIWNDM_GETEND: %ld\n", start + length);
             return (start + length);
         }
 
@@ -743,6 +771,8 @@ end_of_mci_open:
         {
             MCI_STATUS_PARMS mci_status;
 
+            TRACE("MCIWNDM_GETPOSITION\n");
+
             /* get position string if requested */
             if (wParam && lParam)
             {
@@ -782,6 +812,8 @@ end_of_mci_open:
         {
             MCI_STATUS_PARMS mci_status;
 
+            TRACE("MCIWNDM_GETMODE\n");
+
             if (!mwi->mci)
                 return MCI_MODE_NOT_READY;
 
@@ -823,6 +855,8 @@ end_of_mci_open:
         {
             MCI_PLAY_PARMS mci_play;
 
+            TRACE("MCIWNDM_PLAYFROM %08lx\n", lParam);
+
             mci_play.dwCallback = (DWORD_PTR)hWnd;
             mci_play.dwFrom = lParam;
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
@@ -843,6 +877,8 @@ end_of_mci_open:
         {
             MCI_PLAY_PARMS mci_play;
 
+            TRACE("MCIWNDM_PLAYTO %08lx\n", lParam);
+
             mci_play.dwCallback = (DWORD_PTR)hWnd;
             mci_play.dwTo = lParam;
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
@@ -859,12 +895,13 @@ end_of_mci_open:
             return 0;
         }
 
-
     case MCIWNDM_PLAYREVERSE:
         {
             MCI_PLAY_PARMS mci_play;
             DWORD flags = MCI_NOTIFY;
 
+            TRACE("MCIWNDM_PLAYREVERSE %08lx\n", lParam);
+
             mci_play.dwCallback = (DWORD_PTR)hWnd;
             mci_play.dwFrom = lParam;
             switch (mwi->dev_type)
@@ -904,19 +941,25 @@ end_of_mci_open:
 
     case MCIWNDM_GETERRORA:
         mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
+        TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam));
         return mwi->lasterror;
 
     case MCIWNDM_GETERRORW:
         mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
+        TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
         return mwi->lasterror;
 
     case MCIWNDM_SETOWNER:
+        TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam);
         mwi->hwndOwner = (HWND)wParam;
         return 0;
 
     case MCIWNDM_SENDSTRINGA:
         {
             UNICODE_STRING stringW;
+
+            TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam));
+
             RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
             lParam = (LPARAM)stringW.Buffer;
         }
@@ -925,6 +968,8 @@ end_of_mci_open:
         {
             WCHAR *cmdW, *p;
 
+            TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam));
+
             p = strchrW((LPCWSTR)lParam, ' ');
             if (p)
             {
@@ -961,32 +1006,40 @@ end_of_mci_open:
 
     case MCIWNDM_RETURNSTRINGA:
         WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
+        TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam));
         return mwi->lasterror;
 
     case MCIWNDM_RETURNSTRINGW:
         strncpyW((LPWSTR)lParam, mwi->return_string, wParam);
+        TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam));
         return mwi->lasterror;
 
     case MCIWNDM_SETTIMERS:
+        TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam);
         mwi->active_timer = (WORD)wParam;
         mwi->inactive_timer = (WORD)lParam;
         return 0;
 
     case MCIWNDM_SETACTIVETIMER:
+        TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam);
         mwi->active_timer = (WORD)wParam;
         return 0;
 
     case MCIWNDM_SETINACTIVETIMER:
+        TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam);
         mwi->inactive_timer = (WORD)wParam;
         return 0;
 
     case MCIWNDM_GETACTIVETIMER:
+        TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer);
         return mwi->active_timer;
 
     case MCIWNDM_GETINACTIVETIMER:
+        TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer);
         return mwi->inactive_timer;
 
     case MCIWNDM_CHANGESTYLES:
+        TRACE("MCIWNDM_CHANGESTYLES mask %08x, set %08lx\n", wParam, lParam);
         /* FIXME: update the visual window state as well:
          * add/remove trackbar, autosize, etc.
          */
@@ -995,6 +1048,7 @@ end_of_mci_open:
         return 0;
 
     case MCIWNDM_GETSTYLES:
+        TRACE("MCIWNDM_GETSTYLES: %08lx\n", mwi->dwStyle & 0xffff);
         return mwi->dwStyle & 0xffff;
 
     case MCIWNDM_GETDEVICEA:
@@ -1006,6 +1060,7 @@ end_of_mci_open:
             mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
                                              MCI_SYSINFO_INSTALLNAME,
                                              (DWORD_PTR)&mci_sysinfo);
+            TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an((LPSTR)lParam, wParam));
             return 0;
         }
 
@@ -1018,10 +1073,12 @@ end_of_mci_open:
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
                                              MCI_SYSINFO_INSTALLNAME,
                                              (DWORD_PTR)&mci_sysinfo);
+            TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
             return 0;
         }
 
     case MCIWNDM_VALIDATEMEDIA:
+        TRACE("MCIWNDM_VALIDATEMEDIA\n");
         if (mwi->mci)
         {
             SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
@@ -1030,11 +1087,13 @@ end_of_mci_open:
         return 0;
 
     case MCIWNDM_GETFILENAMEA:
+        TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName));
         if (mwi->lpName)
             WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
         return 0;
 
     case MCIWNDM_GETFILENAMEW:
+        TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName));
         if (mwi->lpName)
             strncpyW((LPWSTR)lParam, mwi->lpName, wParam);
         return 0;
@@ -1044,6 +1103,8 @@ end_of_mci_open:
         {
             MCI_STATUS_PARMS mci_status;
 
+            TRACE("MCIWNDM_GETTIMEFORMAT %08x %08lx\n", wParam, lParam);
+
             /* get format string if requested */
             if (wParam && lParam)
             {
@@ -1082,6 +1143,8 @@ end_of_mci_open:
         {
             UNICODE_STRING stringW;
 
+            TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam));
+
             RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
             lParam = (LPARAM)stringW.Buffer;
         }
@@ -1091,6 +1154,8 @@ end_of_mci_open:
             static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
             WCHAR *cmdW;
 
+            TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam));
+
             if (mwi->mci)
             {
                 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
@@ -1112,26 +1177,31 @@ end_of_mci_open:
         }
 
     case MCIWNDM_CAN_PLAY:
+        TRACE("MCIWNDM_CAN_PLAY\n");
         if (mwi->mci)
             return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
         return 0;
 
     case MCIWNDM_CAN_RECORD:
+        TRACE("MCIWNDM_CAN_RECORD\n");
         if (mwi->mci)
             return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
         return 0;
 
     case MCIWNDM_CAN_SAVE:
+        TRACE("MCIWNDM_CAN_SAVE\n");
         if (mwi->mci)
             return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
         return 0;
 
     case MCIWNDM_CAN_EJECT:
+        TRACE("MCIWNDM_CAN_EJECT\n");
         if (mwi->mci)
             return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
         return 0;
 
     case MCIWNDM_CAN_WINDOW:
+        TRACE("MCIWNDM_CAN_WINDOW\n");
         switch (mwi->dev_type)
         {
         case MCI_DEVTYPE_ANIMATION:
@@ -1142,21 +1212,22 @@ end_of_mci_open:
         return 0;
 
     case MCIWNDM_CAN_CONFIG:
+        TRACE("MCIWNDM_CAN_CONFIG\n");
         if (mwi->hdrv)
             return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
         return 0;
 
     case MCIWNDM_SETZOOM:
+        TRACE("MCIWNDM_SETZOOM %ld\n", lParam);
         mwi->zoom = lParam;
 
-        if (mwi->mci)
+        if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW))
         {
             RECT rc;
 
-            SetRectEmpty(&rc);
+            rc.left = rc.top = 0;
             rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
             rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
-            SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
 
             if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
                 rc.bottom += 32; /* add the height of the playbar */
@@ -1167,12 +1238,15 @@ end_of_mci_open:
         return 0;
 
     case MCIWNDM_GETZOOM:
+        TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom);
         return mwi->zoom;
 
     case MCIWNDM_EJECT:
         {
             MCI_SET_PARMS mci_set;
 
+            TRACE("MCIWNDM_EJECT\n");
+
             mci_set.dwCallback = (DWORD_PTR)hWnd;
             mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
                                              MCI_SET_DOOR_OPEN | MCI_NOTIFY,
@@ -1227,6 +1301,8 @@ end_of_mci_open:
                 MCIWND_notify_error(mwi);
                 return mwi->lasterror;
             }
+            /* update window to reflect the state */
+            InvalidateRect(hWnd, NULL, TRUE);
             return 0;
         }
 
@@ -1275,7 +1351,13 @@ end_of_mci_open:
     case MCI_STEP:
     case MCI_STOP:
     case MCI_RESUME:
-        return mci_generic_command(mwi, wMsg);
+        mci_generic_command(mwi, wMsg);
+        if (wMsg == MCI_STEP && !mwi->lasterror)
+        {
+            /* update window to reflect the state */
+            InvalidateRect(hWnd, NULL, TRUE);
+        }
+        return mwi->lasterror;
 
     case MCI_CONFIGURE:
         if (mwi->hdrv)
diff -u cvs/hq/wine/dlls/winmm/mciavi/mciavi.c wine/dlls/winmm/mciavi/mciavi.c
--- cvs/hq/wine/dlls/winmm/mciavi/mciavi.c	2004-02-24 11:56:16.000000000 +0800
+++ wine/dlls/winmm/mciavi/mciavi.c	2004-02-29 00:03:45.000000000 +0800
@@ -152,6 +152,7 @@ static	DWORD	MCIAVI_drvOpen(LPSTR str, L
 	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 dwDev
 	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* 
 	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,41 @@ static	DWORD	MCIAVI_mciPlay(UINT wDevID,
 
     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] = { wma->hStopEvent, wma->hEvent };
+            DWORD ret;
+
 	    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 +601,18 @@ static	DWORD	MCIAVI_mciStop(UINT wDevID,
     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 +699,8 @@ static	DWORD	MCIAVI_mciSeek(UINT wDevID,
     } 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 +820,20 @@ static	DWORD	MCIAVI_mciUpdate(UINT wDevI
 {
     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;
 }
 
diff -u cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c wine/dlls/winmm/mciavi/mmoutput.c
--- cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c	2004-01-29 15:56:07.000000000 +0800
+++ wine/dlls/winmm/mciavi/mmoutput.c	2004-02-29 00:03:45.000000000 +0800
@@ -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* wm
 	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* w
     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* w
     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;
-}
diff -u cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h wine/dlls/winmm/mciavi/private_mciavi.h
--- cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h	2004-01-08 18:28:06.000000000 +0800
+++ wine/dlls/winmm/mciavi/private_mciavi.h	2004-02-29 00:03:45.000000000 +0800
@@ -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 */
diff -u cvs/hq/wine/dlls/winmm/mciavi/wnd.c wine/dlls/winmm/mciavi/wnd.c
--- cvs/hq/wine/dlls/winmm/mciavi/wnd.c	2004-02-28 12:12:28.000000000 +0800
+++ wine/dlls/winmm/mciavi/wnd.c	2004-02-29 00:03:45.000000000 +0800
@@ -73,8 +73,8 @@ static LRESULT WINAPI MCIAVI_WindowProc(
             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, DWOR
             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);






More information about the wine-patches mailing list