PlaySound and al.
Eric Pouech
eric.pouech at wanadoo.fr
Fri May 10 16:08:50 CDT 2002
this patch is a rewrite of the playsound functions
those were a bit buggy and proved to fail in some multi-threaded
environments
the attached patch should take care of that
A+
-------------- next part --------------
Name: playsound
ChangeLog: better behavior of PlaySound (error handling, synchronization)
removed some unnecessary tests about windows' handles
License: X11
GenDate: 2002/05/10 20:54:30 UTC
ModifiedFiles: dlls/winmm/mmsystem.c dlls/winmm/winemm.h
AddedFiles:
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/mmsystem.c,v
retrieving revision 1.51
diff -u -u -r1.51 mmsystem.c
--- dlls/winmm/mmsystem.c 25 Mar 2002 20:53:35 -0000 1.51
+++ dlls/winmm/mmsystem.c 1 Apr 2002 15:25:25 -0000
@@ -218,50 +218,39 @@
memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
}
-static HANDLE PlaySound_hThread = 0;
-static HANDLE PlaySound_hPlayEvent = 0;
-static HANDLE PlaySound_hReadyEvent = 0;
-static HANDLE PlaySound_hMiddleEvent = 0;
-static BOOL PlaySound_Result = FALSE;
-static int PlaySound_Stop = FALSE;
-static int PlaySound_Playing = FALSE;
-
-static LPCSTR PlaySound_pszSound = NULL;
-static HMODULE PlaySound_hmod = 0;
-static DWORD PlaySound_fdwSound = 0;
-static int PlaySound_Loop = FALSE;
-static int PlaySound_SearchMode = 0; /* 1 - sndPlaySound search order
- 2 - PlaySound order */
-
-static HMMIO get_mmioFromFile(LPCSTR lpszName)
+static HMMIO get_mmioFromFile(LPCWSTR lpszName)
{
- return mmioOpenA((LPSTR)lpszName, NULL,
+ return mmioOpenW((LPWSTR)lpszName, NULL,
MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
}
-static HMMIO get_mmioFromProfile(UINT uFlags, LPCSTR lpszName)
+static HMMIO get_mmioFromProfile(UINT uFlags, LPCWSTR lpszName)
{
- char str[128];
- LPSTR ptr;
+ WCHAR str[128];
+ LPWSTR ptr;
HMMIO hmmio;
-
+static WCHAR wszSounds[] = {'S','o','u','n','d','s',0};
+static WCHAR wszDefault[] = {'D','e','f','a','u','l','t',0};
+static WCHAR wszNull[] = {0};
TRACE("searching in SystemSound List !\n");
- GetProfileStringA("Sounds", (LPSTR)lpszName, "", str, sizeof(str));
- if (strlen(str) == 0) {
+ GetProfileStringW(wszSounds, (LPWSTR)lpszName, wszNull, str, sizeof(str)/sizeof(str[0]));
+ if (lstrlenW(str) == 0) {
if (uFlags & SND_NODEFAULT) return 0;
- GetProfileStringA("Sounds", "Default", "", str, sizeof(str));
- if (strlen(str) == 0) return 0;
+ GetProfileStringW(wszSounds, wszDefault, wszNull, str, sizeof(str)/sizeof(str[0]));
+ if (lstrlenW(str) == 0) return 0;
}
- if ((ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0';
- hmmio = get_mmioFromFile(str);
+ for (ptr = str; *ptr && *ptr != ','; ptr++);
+ if (*ptr) *ptr = 0;
+ hmmio = mmioOpenW(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
if (hmmio == 0) {
- WARN("can't find SystemSound='%s' !\n", str);
+ WARN("can't find SystemSound='%s' !\n", debugstr_w(str));
return 0;
}
return hmmio;
}
-struct playsound_data {
+struct playsound_data
+{
HANDLE hEvent;
DWORD dwEventCount;
};
@@ -290,17 +279,17 @@
{
for (;;) {
ResetEvent(s->hEvent);
- if (InterlockedDecrement(&s->dwEventCount) >= 0) {
- break;
- }
+ if (InterlockedDecrement(&s->dwEventCount) >= 0) break;
InterlockedIncrement(&s->dwEventCount);
WaitForSingleObject(s->hEvent, INFINITE);
}
}
-static BOOL WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT uFlags)
+static DWORD WINAPI proc_PlaySound(LPVOID arg)
{
+ WINE_PLAYSOUND* wps = (WINE_PLAYSOUND*)arg;
+ LPWINE_MM_IDATA iData = MULTIMEDIA_GetIData();
BOOL bRet = FALSE;
HMMIO hmmio = 0;
MMCKINFO ckMainRIFF;
@@ -310,43 +299,60 @@
LPWAVEHDR waveHdr = NULL;
INT count, bufsize, left, index;
struct playsound_data s;
+ void* data;
s.hEvent = 0;
- TRACE("SoundName='%s' uFlags=%04X !\n", lpszSoundName, uFlags);
- if (lpszSoundName == NULL) {
- TRACE("Stop !\n");
- return FALSE;
- }
- if (uFlags & SND_MEMORY) {
+ TRACE("SoundName='%s' !\n", debugstr_w(wps->pszSound));
+
+ /* if resource, grab it */
+ if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) {
+ static WCHAR wszWave[] = {'W','A','V','E',0};
+ HRSRC hRes;
+ HGLOBAL hGlob;
+
+ if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 ||
+ (hGlob = LoadResource(wps->hMod, hRes)) == 0) {
+ return FALSE;
+ }
+ if ((data = LockResource(hGlob)) == NULL) {
+ FreeResource(hGlob);
+ return FALSE;
+ }
+ FreeResource(hGlob);
+ } else
+ data = (void*)wps->pszSound;
+
+ /* construct an MMIO stream (either in memory, or from a file */
+ if (wps->fdwSound & SND_MEMORY) { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
MMIOINFO mminfo;
+
memset(&mminfo, 0, sizeof(mminfo));
mminfo.fccIOProc = FOURCC_MEM;
- mminfo.pchBuffer = (LPSTR)lpszSoundName;
- mminfo.cchBuffer = -1;
- TRACE("Memory sound %p\n", lpszSoundName);
- hmmio = mmioOpenA(NULL, &mminfo, MMIO_READ);
+ mminfo.pchBuffer = (LPSTR)data;
+ mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size */
+ TRACE("Memory sound %p\n", data);
+ hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ);
} else {
hmmio = 0;
- if (uFlags & SND_ALIAS)
- if ((hmmio = get_mmioFromProfile(uFlags, lpszSoundName)) == 0)
+ if (wps->fdwSound & SND_ALIAS)
+ if ((hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound)) == 0)
return FALSE;
- if (uFlags & SND_FILENAME)
- if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0) return FALSE;
+ if (wps->fdwSound & SND_FILENAME)
+ if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0) return FALSE;
- if (PlaySound_SearchMode == 1) {
- PlaySound_SearchMode = 0;
- if ((hmmio = get_mmioFromFile(lpszSoundName)) == 0)
- hmmio = get_mmioFromProfile(uFlags, lpszSoundName);
- }
-
- if (PlaySound_SearchMode == 2) {
- PlaySound_SearchMode = 0;
- if ((hmmio = get_mmioFromProfile(uFlags | SND_NODEFAULT, lpszSoundName)) == 0)
- if ((hmmio = get_mmioFromFile(lpszSoundName)) == 0)
- hmmio = get_mmioFromProfile(uFlags, lpszSoundName);
- }
+ switch (wps->searchMode) {
+ case 1:
+ if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0)
+ hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
+ break;
+ case 2:
+ if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, wps->pszSound)) == 0)
+ if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0)
+ hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
+ break;
+ }
}
if (hmmio == 0) return FALSE;
@@ -416,8 +422,8 @@
mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET);
while (left) {
- if (PlaySound_Stop) {
- PlaySound_Stop = PlaySound_Loop = FALSE;
+ if (wps->bStop) {
+ wps->bStop = wps->bLoop = FALSE;
break;
}
count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left));
@@ -425,14 +431,16 @@
left -= count;
waveHdr[index].dwBufferLength = count;
waveHdr[index].dwFlags &= ~WHDR_DONE;
- waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR));
- index ^= 1;
- PlaySound_WaitDone(&s);
+ if (waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR)) == MMSYSERR_NOERROR) {
+ index ^= 1;
+ PlaySound_WaitDone(&s);
+ }
+ else FIXME("Couldn't play header\n");
}
bRet = TRUE;
- } while (PlaySound_Loop);
+ } while (wps->bLoop);
- PlaySound_WaitDone(&s);
+ PlaySound_WaitDone(&s); /* for last buffer */
waveOutReset(hWave);
waveOutUnprepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR));
@@ -445,145 +453,116 @@
if (hWave) while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100);
if (hmmio) mmioClose(hmmio, 0);
+ SetEvent(wps->hReadyEvent);
+ iData->lpPlaySound = NULL;
+
+ /* when filename: HeapFree(GetProcessHeap(), 0, wps->pszSound); */
+ CloseHandle(wps->hReadyEvent);
+ HeapFree(GetProcessHeap(), 0, wps);
+
return bRet;
}
-static DWORD WINAPI PlaySound_Thread(LPVOID arg)
+static BOOL MULTIMEDIA_PlaySound(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound, DWORD search)
{
- DWORD res;
-
- for (;;) {
- PlaySound_Playing = FALSE;
- SetEvent(PlaySound_hReadyEvent);
- res = WaitForSingleObject(PlaySound_hPlayEvent, INFINITE);
- ResetEvent(PlaySound_hReadyEvent);
- SetEvent(PlaySound_hMiddleEvent);
- if (res == WAIT_FAILED) ExitThread(2);
- if (res != WAIT_OBJECT_0) continue;
- PlaySound_Playing = TRUE;
-
- if ((PlaySound_fdwSound & SND_RESOURCE) == SND_RESOURCE) {
- HRSRC hRES;
- HGLOBAL hGLOB;
- void* ptr;
-
- if ((hRES = FindResourceA(PlaySound_hmod, PlaySound_pszSound, "WAVE")) == 0) {
- PlaySound_Result = FALSE;
- continue;
- }
- if ((hGLOB = LoadResource(PlaySound_hmod, hRES)) == 0) {
- PlaySound_Result = FALSE;
- continue;
- }
- if ((ptr = LockResource(hGLOB)) == NULL) {
- FreeResource(hGLOB);
- PlaySound_Result = FALSE;
- continue;
- }
- PlaySound_Result = proc_PlaySound(ptr,
- ((UINT16)PlaySound_fdwSound ^ SND_RESOURCE) | SND_MEMORY);
- FreeResource(hGLOB);
- continue;
- }
- PlaySound_Result = proc_PlaySound(PlaySound_pszSound, (UINT16)PlaySound_fdwSound);
- }
-}
+ WINE_PLAYSOUND* wps = NULL;
+ DWORD id;
+ LPWINE_MM_IDATA iData = MULTIMEDIA_GetIData();
+ BOOL bRet = FALSE;
-/**************************************************************************
- * @ [WINMM.1]
- * PlaySound [WINMM.@]
- * PlaySoundA [WINMM.@]
- */
-BOOL WINAPI PlaySoundA(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound)
-{
- static LPSTR StrDup = NULL;
-
TRACE("pszSound='%p' hmod=%04X fdwSound=%08lX\n",
pszSound, hmod, fdwSound);
- if (PlaySound_hThread == 0) { /* This is the first time they called us */
- DWORD id;
- if ((PlaySound_hReadyEvent = CreateEventA(NULL, TRUE, FALSE, NULL)) == 0)
- return FALSE;
- if ((PlaySound_hMiddleEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
- return FALSE;
- if ((PlaySound_hPlayEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
- return FALSE;
- if ((PlaySound_hThread = CreateThread(NULL, 0, PlaySound_Thread, 0, 0, &id)) == 0)
- return FALSE;
- }
-
- /* FIXME? I see no difference between SND_WAIT and SND_NOSTOP ! */
- if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySound_Playing)
- return FALSE;
-
- /* Trying to stop if playing */
- if (PlaySound_Playing) PlaySound_Stop = TRUE;
-
- /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave*/
- if (WaitForSingleObject(PlaySound_hReadyEvent, 1000*10) != WAIT_OBJECT_0)
+ /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
+ * there could be one if several sounds can be played at once...
+ */
+ if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && iData->lpPlaySound)
return FALSE;
- if (!pszSound || (fdwSound & SND_PURGE))
- return TRUE; /* We stopped playing so leaving */
-
- if (PlaySound_SearchMode != 1) PlaySound_SearchMode = 2;
- if (!(fdwSound & SND_ASYNC)) {
- if (fdwSound & SND_LOOP)
- return FALSE;
- PlaySound_pszSound = pszSound;
- PlaySound_hmod = hmod;
- PlaySound_fdwSound = fdwSound;
- PlaySound_Result = FALSE;
- SetEvent(PlaySound_hPlayEvent);
- if (WaitForSingleObject(PlaySound_hMiddleEvent, INFINITE) != WAIT_OBJECT_0)
- return FALSE;
- if (WaitForSingleObject(PlaySound_hReadyEvent, INFINITE) != WAIT_OBJECT_0)
- return FALSE;
- return PlaySound_Result;
- } else {
- PlaySound_hmod = hmod;
- PlaySound_fdwSound = fdwSound;
- PlaySound_Result = FALSE;
- if (StrDup) {
- HeapFree(GetProcessHeap(), 0, StrDup);
- StrDup = NULL;
- }
- if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
- !((DWORD)pszSound >> 16)) || !pszSound))
+ do {
+ HANDLE hEvt = 0;
+
+ /* Trying to stop if playing */
+ EnterCriticalSection(&iData->cs);
+ if (iData->lpPlaySound) {
+ LPWINE_PLAYSOUND ps2stop = iData->lpPlaySound;
+
+ hEvt = ps2stop->hReadyEvent;
+ ps2stop->bStop = TRUE;
+ }
+ LeaveCriticalSection(&iData->cs);
+ /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave
+ * FIXME: race here (if hEvt is destroyed and reallocated - as a handle - to
+ * another object)... unlikely but possible
+ */
+ if (hEvt) WaitForSingleObject(hEvt, 1000*10);
+
+ if (!pszSound || (fdwSound & SND_PURGE))
+ return TRUE; /* We stopped playing so leaving */
+
+ if (wps == NULL)
{
- StrDup = HeapAlloc(GetProcessHeap(), 0, strlen(pszSound)+1 );
- strcpy( StrDup, pszSound );
- PlaySound_pszSound = StrDup;
- } else PlaySound_pszSound = pszSound;
- PlaySound_Loop = fdwSound & SND_LOOP;
- SetEvent(PlaySound_hPlayEvent);
- ResetEvent(PlaySound_hMiddleEvent);
+ wps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wps));
+ if (!wps) return FALSE;
+
+ wps->searchMode = search;
+ wps->hMod = hmod;
+ wps->fdwSound = fdwSound;
+ wps->pszSound = pszSound;
+ if ((wps->hReadyEvent = CreateEventA(NULL, TRUE, FALSE, NULL)) == 0)
+ goto cleanup;
+ }
+ } while (InterlockedCompareExchangePointer((void**)&iData->lpPlaySound, wps, NULL) != NULL);
+
+ if (fdwSound & SND_ASYNC) {
+ if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
+ !((DWORD)pszSound >> 16)) ||
+ !pszSound)) {
+ wps->pszSound = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pszSound)+1) * sizeof(WCHAR) );
+ lstrcpyW((LPWSTR)wps->pszSound, pszSound);
+ }
+ wps->bLoop = fdwSound & SND_LOOP;
+ /* FIXME: memory leak in case of error & cs is still lock */
+ if ((wps->hThread = CreateThread(NULL, 0, proc_PlaySound, wps, 0, &id)) == 0)
+ return FALSE;
+
return TRUE;
}
- return FALSE;
+
+ bRet = proc_PlaySound(wps);
+ cleanup:
+ return bRet;
}
/**************************************************************************
- * PlaySoundW [WINMM.@]
+ * PlaySoundA [WINMM.@]
*/
-BOOL WINAPI PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
+BOOL WINAPI PlaySoundA(LPCSTR pszSoundA, HMODULE hmod, DWORD fdwSound)
{
- LPSTR pszSoundA;
+ LPWSTR pszSoundW;
BOOL bSound;
- if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
- !((DWORD)pszSound >> 16)) || !pszSound)) {
- pszSoundA = HEAP_strdupWtoA(GetProcessHeap(), 0,pszSound);
- bSound = PlaySoundA(pszSoundA, hmod, fdwSound);
- HeapFree(GetProcessHeap(), 0, pszSoundA);
+ if (!((fdwSound & SND_MEMORY) ||
+ ((fdwSound & SND_RESOURCE) && !((DWORD)pszSoundA >> 16)) ||
+ !pszSoundA)) {
+ pszSoundW = HEAP_strdupAtoW(GetProcessHeap(), 0, pszSoundA);
+ bSound = PlaySoundW(pszSoundW, hmod, fdwSound);
+ HeapFree(GetProcessHeap(), 0, pszSoundW);
} else
- bSound = PlaySoundA((LPCSTR)pszSound, hmod, fdwSound);
+ bSound = PlaySoundW((LPWSTR)pszSoundA, hmod, fdwSound);
return bSound;
}
/**************************************************************************
+ * PlaySoundW [WINMM.@]
+ */
+BOOL WINAPI PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
+{
+ return MULTIMEDIA_PlaySound(pszSound, hmod, fdwSound, 2);
+}
+
+/**************************************************************************
* PlaySound [MMSYSTEM.3]
*/
BOOL16 WINAPI PlaySound16(LPCSTR pszSound, HMODULE16 hmod, DWORD fdwSound)
@@ -601,19 +580,29 @@
/**************************************************************************
* sndPlaySoundA [WINMM.@]
*/
-BOOL WINAPI sndPlaySoundA(LPCSTR lpszSoundName, UINT uFlags)
+BOOL WINAPI sndPlaySoundA(LPCSTR pszSoundA, UINT uFlags)
{
- PlaySound_SearchMode = 1;
- return PlaySoundA(lpszSoundName, 0, uFlags);
+ LPWSTR pszSoundW;
+ BOOL bSound;
+
+ if (!((uFlags & SND_MEMORY) ||
+ ((uFlags & SND_RESOURCE) && !((DWORD)pszSoundA >> 16)) ||
+ !pszSoundA)) {
+ pszSoundW = HEAP_strdupAtoW(GetProcessHeap(), 0, pszSoundA);
+ bSound = sndPlaySoundW(pszSoundW, uFlags);
+ HeapFree(GetProcessHeap(), 0, pszSoundW);
+ } else
+ bSound = sndPlaySoundW((LPWSTR)pszSoundA, uFlags);
+
+ return bSound;
}
/**************************************************************************
* sndPlaySoundW [WINMM.@]
*/
-BOOL WINAPI sndPlaySoundW(LPCWSTR lpszSoundName, UINT uFlags)
+BOOL WINAPI sndPlaySoundW(LPCWSTR pszSound, UINT uFlags)
{
- PlaySound_SearchMode = 1;
- return PlaySoundW(lpszSoundName, 0, uFlags);
+ return MULTIMEDIA_PlaySound(pszSound, 0, uFlags, 1);
}
/**************************************************************************
@@ -625,13 +614,12 @@
DWORD lc;
ReleaseThunkLock(&lc);
- retv = sndPlaySoundA( lpszSoundName, uFlags );
+ retv = sndPlaySoundA(lpszSoundName, uFlags);
RestoreThunkLock(lc);
return retv;
}
-
/**************************************************************************
* mmsystemGetVersion [MMSYSTEM.5]
* return value borrowed from Win95 winmm.dll ;)
@@ -668,9 +656,7 @@
break;
case DCB_WINDOW:
TRACE("Window(%04lX) handle=%04X!\n", dwCallBack, hDev);
- if (!IsWindow(dwCallBack))
- return FALSE;
- PostMessageA((HWND16)dwCallBack, wMsg, hDev, dwParam1);
+ PostMessageA((HWND)dwCallBack, wMsg, hDev, dwParam1);
break;
case DCB_TASK: /* aka DCB_THREAD */
TRACE("Task(%04lx) !\n", dwCallBack);
@@ -1584,13 +1570,7 @@
{
TRACE("(%04X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
- if (!IsWindow(hWndCallBack)) {
- WARN("bad hWnd for call back (0x%04x)\n", hWndCallBack);
- return FALSE;
- }
- TRACE("before PostMessage\n");
- PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
- return TRUE;
+ return PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
}
/**************************************************************************
@@ -1601,13 +1581,7 @@
TRACE("(%08X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
- if (!IsWindow(hWndCallBack)) {
- WARN("bad hWnd for call back (0x%04x)\n", hWndCallBack);
- return FALSE;
- }
- TRACE("before PostMessage\n");
- PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
- return TRUE;
+ return PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
}
/**************************************************************************
Index: dlls/winmm/winemm.h
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/winemm.h,v
retrieving revision 1.10
diff -u -u -r1.10 winemm.h
--- dlls/winmm/winemm.h 9 Mar 2002 23:44:33 -0000 1.10
+++ dlls/winmm/winemm.h 23 Apr 2002 19:16:52 -0000
@@ -155,6 +155,18 @@
DWORD dwFileSize;
} WINE_MMIO, *LPWINE_MMIO;
+typedef struct tagWINE_PLAYSOUND {
+ HANDLE hThread;
+ HANDLE hReadyEvent;
+ BOOL bStop;
+ LPCWSTR pszSound;
+ HMODULE hMod;
+ DWORD fdwSound;
+ int bLoop;
+ int searchMode; /* 1 - sndPlaySound search order
+ 2 - PlaySound order */
+} WINE_PLAYSOUND, *LPWINE_PLAYSOUND;
+
typedef struct tagWINE_MM_IDATA {
/* iData reference */
DWORD dwThisProcess;
@@ -178,6 +190,8 @@
/* LPWINE_MIXER lpMixer; */
/* mmio part */
LPWINE_MMIO lpMMIO;
+ /* playsound and sndPlaySound */
+ LPWINE_PLAYSOUND lpPlaySound;
} WINE_MM_IDATA, *LPWINE_MM_IDATA;
/* function prototypes */
More information about the wine-patches
mailing list