Commit 197607db authored by Jörg Höhle's avatar Jörg Höhle Committed by Alexandre Julliard

winmm: Allow new sounds to interrupt previous PlaySound invocations.

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