Just update from/to pointers and exit on a subsequent MCI_PLAY command

Dmitry Timoshkov dmitry at baikal.ru
Fri Mar 19 05:26:15 CST 2004


Hello,

PowerPoint XP continuously sends MCI_PLAY commands to MCIWnd window,
which in turn sends asynchronous MCI_PLAY commands to mciavi driver.
That leads to huge amount of new threads each playing the same AVI clip.

A test under Windows shows that mciavi driver simply updates its from/to
pointers without interrupting current play operation.

I've included my previous patch here, it not only helps to avoid a dead lock,
but also makes AVI playback loop react much snappier on the stop command.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Just update from/to pointers and exit on a subsequent MCI_PLAY command.

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-03-18 21:32:17.000000000 +0800
+++ wine/dlls/winmm/mciavi/mciavi.c	2004-03-19 19:08:00.000000000 +0800
@@ -427,7 +427,6 @@ static	DWORD	MCIAVI_mciPlay(UINT wDevID,
         return MCIERR_NO_WINDOW;
     }
 
-    wma->dwStatus = MCI_MODE_PLAY;
     LeaveCriticalSection(&wma->cs);
 
     if (!(dwFlags & MCI_WAIT)) {
@@ -435,7 +434,8 @@ static	DWORD	MCIAVI_mciPlay(UINT wDevID,
                                    (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
     }
 
-    ShowWindow(wma->hWndPaint, SW_SHOWNA);
+    if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
+        ShowWindow(wma->hWndPaint, SW_SHOWNA);
 
     EnterCriticalSection(&wma->cs);
 
@@ -454,13 +454,23 @@ static	DWORD	MCIAVI_mciPlay(UINT wDevID,
     TRACE("Playing from frame=%lu to frame=%lu\n", dwFromFrame, dwToFrame);
 
     wma->dwCurrVideoFrame = dwFromFrame;
+    wma->dwToVideoFrame = dwToFrame;
 
-    if (dwToFrame <= wma->dwCurrVideoFrame)
+    /* if already playing exit */
+    if (wma->dwStatus == MCI_MODE_PLAY)
+    {
+        LeaveCriticalSection(&wma->cs);
+        return 0;
+    }
+
+    if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
     {
         dwRet = 0;
         goto mci_play_done;
     }
 
+    wma->dwStatus = MCI_MODE_PLAY;
+
     if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_DGV_PLAY_REVERSE|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN))
 	FIXME("Unsupported flag %08lx\n", dwFlags);
 
@@ -610,7 +620,9 @@ static	DWORD	MCIAVI_mciStop(UINT wDevID,
     switch (wma->dwStatus) {
     case MCI_MODE_PLAY:
     case MCI_MODE_RECORD:
+        LeaveCriticalSection(&wma->cs);
         SetEvent(wma->hStopEvent);
+        EnterCriticalSection(&wma->cs);
         /* fall through */
     case MCI_MODE_PAUSE:
 	/* Since our wave notification callback takes the lock,
@@ -648,6 +660,8 @@ static	DWORD	MCIAVI_mciPause(UINT wDevID
 {
     WINE_MCIAVI *wma;
 
+    TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
+
     wma = MCIAVI_mciGetOpenDev(wDevID);
     if (wma == NULL)		return MCIERR_INVALID_DEVICE_ID;
 
@@ -660,7 +674,7 @@ static	DWORD	MCIAVI_mciPause(UINT wDevID
     	LeaveCriticalSection(&wma->cs);
 	return waveOutPause(wma->hWave);
     }
-       
+
     LeaveCriticalSection(&wma->cs);
     return 0;
 }
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-03-02 18:40:20.000000000 +0800
+++ wine/dlls/winmm/mciavi/private_mciavi.h	2004-03-19 19:09:12.000000000 +0800
@@ -76,6 +76,7 @@ typedef struct {
     HWND               hWnd, hWndPaint;
     DWORD               dwCachedFrame; /* buffered frame */
     DWORD		dwCurrVideoFrame;	/* video frame to display and current position */
+    DWORD               dwToVideoFrame; /* play to */
     DWORD		dwCurrAudioBlock;	/* current audio block being played */
     RECT                source, dest;
     /* data for the background mechanism */






More information about the wine-patches mailing list