=?UTF-8?Q?J=C3=B6rg=20H=C3=B6hle=20?=: winmm: Allow new sounds to interrupt previous PlaySound invocations.

Alexandre Julliard julliard at winehq.org
Thu Feb 16 13:10:46 CST 2012


Module: wine
Branch: master
Commit: 197607db2e06f28b666da9ce88b69c9994c1bb65
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=197607db2e06f28b666da9ce88b69c9994c1bb65

Author: Jörg Höhle <hoehle at users.sourceforge.net>
Date:   Tue Feb 14 19:27:30 2012 +0100

winmm: Allow new sounds to interrupt previous PlaySound invocations.

---

 dlls/winmm/playsound.c |   34 ++++++++++++++++++++--------------
 1 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/dlls/winmm/playsound.c b/dlls/winmm/playsound.c
index 02e24e8..e5b820b 100644
--- a/dlls/winmm/playsound.c
+++ b/dlls/winmm/playsound.c
@@ -44,10 +44,10 @@ typedef struct tagWINE_PLAYSOUND
     LPCWSTR                     pszSound;
     HMODULE                     hMod;
     DWORD                       fdwSound;
-    struct tagWINE_PLAYSOUND*   lpNext;
+    HWAVEOUT                    hWave;
 } WINE_PLAYSOUND;
 
-static WINE_PLAYSOUND *PlaySoundList;
+static WINE_PLAYSOUND *PlaySoundCurrent;
 static BOOL bPlaySoundStop;
 
 static HMMIO	get_mmioFromFile(LPCWSTR lpszName)
@@ -206,12 +206,9 @@ static BOOL PlaySound_IsString(DWORD fdwSound, const void* psz)
 
 static void     PlaySound_Free(WINE_PLAYSOUND* wps)
 {
-    WINE_PLAYSOUND**    p;
-
     EnterCriticalSection(&WINMM_cs);
-    for (p = &PlaySoundList; *p && *p != wps; p = &((*p)->lpNext));
-    if (*p) *p = (*p)->lpNext;
-    if (PlaySoundList == NULL) SetEvent(psLastEvent);
+    PlaySoundCurrent = NULL;
+    SetEvent(psLastEvent);
     LeaveCriticalSection(&WINMM_cs);
     if (wps->bAlloc) HeapFree(GetProcessHeap(), 0, (void*)wps->pszSound);
     HeapFree(GetProcessHeap(), 0, wps);
@@ -399,7 +396,7 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
 	  (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);
 
     s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!s.hEvent)
+    if (!s.hEvent || bPlaySoundStop)
 	goto errCleanUp;
 
     if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD_PTR)PlaySound_Callback,
@@ -423,6 +420,7 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
 	goto errCleanUp;
     }
 
+    wps->hWave = hWave;
     s.dwEventCount = 1L; /* for first buffer */
     index = 0;
 
@@ -434,7 +432,6 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
         {
 	    if (bPlaySoundStop)
             {
-		waveOutReset(hWave);
 		wps->bLoop = FALSE;
 		break;
 	    }
@@ -464,7 +461,15 @@ static DWORD WINAPI proc_PlaySound(LPVOID arg)
 errCleanUp:
     TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko");
     HeapFree(GetProcessHeap(), 0, lpWaveFormat);
-    if (hWave)		while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100);
+    if (hWave)
+    {
+        EnterCriticalSection(&WINMM_cs);
+        /* the CS prevents a concurrent waveOutReset */
+        wps->hWave = 0;
+        LeaveCriticalSection(&WINMM_cs);
+        while (waveOutClose(hWave) == WAVERR_STILLPLAYING)
+            Sleep(100);
+    }
     CloseHandle(s.hEvent);
     HeapFree(GetProcessHeap(), 0, waveHdr);
     if (hmmio) 		mmioClose(hmmio, 0);
@@ -482,7 +487,7 @@ static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSo
 	  pszSound, hmod, fdwSound);
 
     /* SND_NOWAIT is ignored in w95/2k/xp. */
-    if ((fdwSound & SND_NOSTOP) && PlaySoundList != NULL)
+    if ((fdwSound & SND_NOSTOP) && PlaySoundCurrent != NULL)
 	return FALSE;
 
     /* alloc internal structure, if we need to play something */
@@ -496,12 +501,14 @@ static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSo
     /* since several threads can enter PlaySound in parallel, we're not
      * sure, at this point, that another thread didn't start a new playsound
      */
-    while (PlaySoundList != NULL)
+    while (PlaySoundCurrent != NULL)
     {
         ResetEvent(psLastEvent);
         /* FIXME: doc says we have to stop all instances of pszSound if it's non
          * NULL... as of today, we stop all playing instances */
         bPlaySoundStop = TRUE;
+        if(PlaySoundCurrent->hWave)
+            waveOutReset(PlaySoundCurrent->hWave);
 
         LeaveCriticalSection(&WINMM_cs);
         WaitForSingleObject(psLastEvent, INFINITE);
@@ -510,8 +517,7 @@ static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSo
         bPlaySoundStop = FALSE;
     }
 
-    if (wps) wps->lpNext = PlaySoundList;
-    PlaySoundList = wps;
+    PlaySoundCurrent = wps;
     LeaveCriticalSection(&WINMM_cs);
 
     if (!wps) return TRUE;




More information about the wine-cvs mailing list