ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

playsound.c
Go to the documentation of this file.
00001 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
00002 
00003 /*
00004  * MMSYSTEM functions
00005  *
00006  * Copyright 1993      Martin Ayotte
00007  *           1998-2002 Eric Pouech
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include <stdarg.h>
00025 #include <string.h>
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "mmsystem.h"
00030 #include "wingdi.h"
00031 #include "winuser.h"
00032 #include "winreg.h"
00033 #include "winemm.h"
00034 #include "winternl.h"
00035 
00036 #include "wine/debug.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
00039 
00040 typedef struct tagWINE_PLAYSOUND
00041 {
00042     unsigned                    bLoop : 1,
00043                                 bAlloc : 1;
00044     LPCWSTR                     pszSound;
00045     HMODULE                     hMod;
00046     DWORD                       fdwSound;
00047     HANDLE                      hThread;
00048     HWAVEOUT                    hWave;
00049     struct tagWINE_PLAYSOUND*   lpNext;
00050 } WINE_PLAYSOUND;
00051 
00052 static WINE_PLAYSOUND *PlaySoundList;
00053 
00054 static HMMIO    get_mmioFromFile(LPCWSTR lpszName)
00055 {
00056     HMMIO       ret;
00057     WCHAR       buf[256];
00058     LPWSTR      dummy;
00059 
00060     ret = mmioOpenW((LPWSTR)lpszName, NULL,
00061                     MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
00062     if (ret != 0) return ret;
00063     if (SearchPathW(NULL, lpszName, NULL, sizeof(buf)/sizeof(buf[0]), buf, &dummy))
00064     {
00065         return mmioOpenW(buf, NULL,
00066                          MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
00067     }
00068     return 0;
00069 }
00070 
00071 static HMMIO    get_mmioFromProfile(UINT uFlags, LPCWSTR lpszName)
00072 {
00073     WCHAR   str[128];
00074     LPWSTR  ptr;
00075     HMMIO   hmmio;
00076     HKEY        hRegSnd, hRegApp, hScheme, hSnd;
00077     DWORD       err, type, count;
00078 
00079     static const WCHAR  wszSounds[] = {'S','o','u','n','d','s',0};
00080     static const WCHAR  wszDefault[] = {'D','e','f','a','u','l','t',0};
00081     static const WCHAR  wszKey[] = {'A','p','p','E','v','e','n','t','s','\\',
00082                                     'S','c','h','e','m','e','s','\\',
00083                                     'A','p','p','s',0};
00084     static const WCHAR  wszDotDefault[] = {'.','D','e','f','a','u','l','t',0};
00085     static const WCHAR  wszDotCurrent[] = {'.','C','u','r','r','e','n','t',0};
00086     static const WCHAR  wszNull[] = {0};
00087 
00088     TRACE("searching in SystemSound list for %s\n", debugstr_w(lpszName));
00089     GetProfileStringW(wszSounds, lpszName, wszNull, str, sizeof(str)/sizeof(str[0]));
00090     if (lstrlenW(str) == 0)
00091     {
00092     if (uFlags & SND_NODEFAULT) goto next;
00093     GetProfileStringW(wszSounds, wszDefault, wszNull, str, sizeof(str)/sizeof(str[0]));
00094     if (lstrlenW(str) == 0) goto next;
00095     }
00096     for (ptr = str; *ptr && *ptr != ','; ptr++);
00097     if (*ptr) *ptr = 0;
00098     hmmio = mmioOpenW(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
00099     if (hmmio != 0) return hmmio;
00100  next:
00101     /* we look up the registry under
00102      *      HKCU\AppEvents\Schemes\Apps\.Default
00103      *      HKCU\AppEvents\Schemes\Apps<AppName>
00104      */
00105     if (RegOpenKeyW(HKEY_CURRENT_USER, wszKey, &hRegSnd) != 0) goto none;
00106     if (uFlags & SND_APPLICATION)
00107     {
00108         DWORD len;
00109 
00110         err = 1; /* error */
00111         len = GetModuleFileNameW(0, str, sizeof(str)/sizeof(str[0]));
00112         if (len > 0 && len < sizeof(str)/sizeof(str[0]))
00113         {
00114             for (ptr = str + lstrlenW(str) - 1; ptr >= str; ptr--)
00115             {
00116                 if (*ptr == '.') *ptr = 0;
00117                 if (*ptr == '\\')
00118                 {
00119                     err = RegOpenKeyW(hRegSnd, ptr+1, &hRegApp);
00120                     break;
00121                 }
00122             }
00123         }
00124     }
00125     else
00126     {
00127         err = RegOpenKeyW(hRegSnd, wszDotDefault, &hRegApp);
00128     }
00129     RegCloseKey(hRegSnd);
00130     if (err != 0) goto none;
00131     err = RegOpenKeyW(hRegApp, lpszName, &hScheme);
00132     RegCloseKey(hRegApp);
00133     if (err != 0) goto none;
00134     /* what's the difference between .Current and .Default ? */
00135     err = RegOpenKeyW(hScheme, wszDotDefault, &hSnd);
00136     if (err != 0)
00137     {
00138         err = RegOpenKeyW(hScheme, wszDotCurrent, &hSnd);
00139         RegCloseKey(hScheme);
00140         if (err != 0)
00141             goto none;
00142     }
00143     count = sizeof(str)/sizeof(str[0]);
00144     err = RegQueryValueExW(hSnd, NULL, 0, &type, (LPBYTE)str, &count);
00145     RegCloseKey(hSnd);
00146     if (err != 0 || !*str) goto none;
00147     hmmio = mmioOpenW(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
00148     if (hmmio) return hmmio;
00149  none:
00150     WARN("can't find SystemSound=%s !\n", debugstr_w(lpszName));
00151     return 0;
00152 }
00153 
00154 struct playsound_data
00155 {
00156     HANDLE  hEvent;
00157     LONG    dwEventCount;
00158 };
00159 
00160 static void CALLBACK PlaySound_Callback(HWAVEOUT hwo, UINT uMsg,
00161                     DWORD_PTR dwInstance,
00162                     DWORD_PTR dwParam1, DWORD_PTR dwParam2)
00163 {
00164     struct playsound_data*  s = (struct playsound_data*)dwInstance;
00165 
00166     switch (uMsg) {
00167     case WOM_OPEN:
00168     case WOM_CLOSE:
00169     break;
00170     case WOM_DONE:
00171     InterlockedIncrement(&s->dwEventCount);
00172     TRACE("Returning waveHdr=%lx\n", dwParam1);
00173     SetEvent(s->hEvent);
00174     break;
00175     default:
00176     ERR("Unknown uMsg=%d\n", uMsg);
00177     }
00178 }
00179 
00180 static void PlaySound_WaitDone(struct playsound_data* s)
00181 {
00182     for (;;) {
00183     ResetEvent(s->hEvent);
00184     if (InterlockedDecrement(&s->dwEventCount) >= 0) break;
00185     InterlockedIncrement(&s->dwEventCount);
00186 
00187     WaitForSingleObject(s->hEvent, INFINITE);
00188     }
00189 }
00190 
00191 static BOOL PlaySound_IsString(DWORD fdwSound, const void* psz)
00192 {
00193     /* SND_RESOURCE is 0x40004 while
00194      * SND_MEMORY is 0x00004
00195      */
00196     switch (fdwSound & (SND_RESOURCE|SND_ALIAS_ID|SND_FILENAME))
00197     {
00198     case SND_RESOURCE:  return HIWORD(psz) != 0; /* by name or by ID ? */
00199     case SND_ALIAS_ID:
00200     case SND_MEMORY:    return FALSE;
00201     case SND_ALIAS:
00202     case SND_FILENAME:
00203     case 0:             return TRUE;
00204     default:            FIXME("WTF\n"); return FALSE;
00205     }
00206 }
00207 
00208 static void     PlaySound_Free(WINE_PLAYSOUND* wps)
00209 {
00210     WINE_PLAYSOUND**    p;
00211 
00212     EnterCriticalSection(&WINMM_cs);
00213     for (p = &PlaySoundList; *p && *p != wps; p = &((*p)->lpNext));
00214     if (*p) *p = (*p)->lpNext;
00215     if (PlaySoundList == NULL) SetEvent(psLastEvent);
00216     LeaveCriticalSection(&WINMM_cs);
00217     if (wps->bAlloc) HeapFree(GetProcessHeap(), 0, (void*)wps->pszSound);
00218     if (wps->hThread) CloseHandle(wps->hThread);
00219     HeapFree(GetProcessHeap(), 0, wps);
00220 }
00221 
00222 static WINE_PLAYSOUND*  PlaySound_Alloc(const void* pszSound, HMODULE hmod,
00223                                         DWORD fdwSound, BOOL bUnicode)
00224 {
00225     WINE_PLAYSOUND* wps;
00226 
00227     wps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wps));
00228     if (!wps) return NULL;
00229 
00230     wps->hMod = hmod;
00231     wps->fdwSound = fdwSound;
00232     if (PlaySound_IsString(fdwSound, pszSound))
00233     {
00234         if (bUnicode)
00235         {
00236             if (fdwSound & SND_ASYNC)
00237             {
00238                 LPWSTR sound = HeapAlloc(GetProcessHeap(), 0,
00239                                          (lstrlenW(pszSound)+1) * sizeof(WCHAR));
00240                 if (!sound) goto oom_error;
00241                 wps->pszSound = lstrcpyW(sound, pszSound);
00242                 wps->bAlloc = TRUE;
00243             }
00244             else
00245                 wps->pszSound = pszSound;
00246         }
00247         else
00248         {
00249             UNICODE_STRING usBuffer;
00250             RtlCreateUnicodeStringFromAsciiz(&usBuffer, pszSound);
00251             wps->pszSound = usBuffer.Buffer;
00252             if (!wps->pszSound) goto oom_error;
00253             wps->bAlloc = TRUE;
00254         }
00255     }
00256     else
00257         wps->pszSound = pszSound;
00258 
00259     return wps;
00260  oom_error:
00261     PlaySound_Free(wps);
00262     return NULL;
00263 }
00264 
00265 static DWORD WINAPI proc_PlaySound(LPVOID arg)
00266 {
00267     WINE_PLAYSOUND*     wps = arg;
00268     BOOL        bRet = FALSE;
00269     HMMIO       hmmio = 0;
00270     MMCKINFO        ckMainRIFF;
00271     MMCKINFO            mmckInfo;
00272     LPWAVEFORMATEX      lpWaveFormat = NULL;
00273     LPWAVEHDR       waveHdr = NULL;
00274     INT         count, bufsize, left, index;
00275     struct playsound_data   s;
00276     void*               data;
00277 
00278     s.hEvent = 0;
00279 
00280     TRACE("SoundName=%s !\n", debugstr_w(wps->pszSound));
00281 
00282     /* if resource, grab it */
00283     if ((wps->fdwSound & SND_RESOURCE) == SND_RESOURCE) {
00284         static const WCHAR wszWave[] = {'W','A','V','E',0};
00285         HRSRC   hRes;
00286         HGLOBAL hGlob;
00287 
00288         if ((hRes = FindResourceW(wps->hMod, wps->pszSound, wszWave)) == 0 ||
00289             (hGlob = LoadResource(wps->hMod, hRes)) == 0)
00290             goto errCleanUp;
00291         if ((data = LockResource(hGlob)) == NULL) {
00292             FreeResource(hGlob);
00293             goto errCleanUp;
00294         }
00295         FreeResource(hGlob);
00296     } else
00297         data = (void*)wps->pszSound;
00298 
00299     /* construct an MMIO stream (either in memory, or from a file */
00300     if (wps->fdwSound & SND_MEMORY)
00301     { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
00302     MMIOINFO    mminfo;
00303 
00304     memset(&mminfo, 0, sizeof(mminfo));
00305     mminfo.fccIOProc = FOURCC_MEM;
00306     mminfo.pchBuffer = data;
00307     mminfo.cchBuffer = -1; /* FIXME: when a resource, could grab real size */
00308     TRACE("Memory sound %p\n", data);
00309     hmmio = mmioOpenW(NULL, &mminfo, MMIO_READ);
00310     }
00311     else if (wps->fdwSound & SND_ALIAS)
00312     {
00313         if ((wps->fdwSound & SND_ALIAS_ID) == SND_ALIAS_ID)
00314         {
00315             static const WCHAR  wszSystemAsterisk[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0};
00316             static const WCHAR  wszSystemDefault[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t',0};
00317             static const WCHAR  wszSystemExclamation[] = {'S','y','s','t','e','m','E','x','c','l','a','m','a','t','i','o','n',0};
00318             static const WCHAR  wszSystemExit[] = {'S','y','s','t','e','m','E','x','i','t',0};
00319             static const WCHAR  wszSystemHand[] = {'S','y','s','t','e','m','H','a','n','d',0};
00320             static const WCHAR  wszSystemQuestion[] = {'S','y','s','t','e','m','Q','u','e','s','t','i','o','n',0};
00321             static const WCHAR  wszSystemStart[] = {'S','y','s','t','e','m','S','t','a','r','t',0};
00322             static const WCHAR  wszSystemWelcome[] = {'S','y','s','t','e','m','W','e','l','c','o','m','e',0};
00323 
00324             wps->fdwSound &= ~(SND_ALIAS_ID ^ SND_ALIAS);
00325             if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMASTERISK)
00326                 wps->pszSound = wszSystemAsterisk;
00327             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMDEFAULT)
00328                 wps->pszSound = wszSystemDefault;
00329             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXCLAMATION)
00330                 wps->pszSound = wszSystemExclamation;
00331             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMEXIT)
00332                 wps->pszSound = wszSystemExit;
00333             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMHAND)
00334                 wps->pszSound = wszSystemHand;
00335             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMQUESTION)
00336                 wps->pszSound = wszSystemQuestion;
00337             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMSTART)
00338                 wps->pszSound = wszSystemStart;
00339             else if (wps->pszSound == (LPCWSTR)SND_ALIAS_SYSTEMWELCOME)
00340                 wps->pszSound = wszSystemWelcome;
00341             else goto errCleanUp;
00342         }
00343         hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
00344     }
00345     else if (wps->fdwSound & SND_FILENAME)
00346     {
00347         hmmio = get_mmioFromFile(wps->pszSound);
00348     }
00349     else
00350     {
00351         if ((hmmio = get_mmioFromProfile(wps->fdwSound | SND_NODEFAULT, wps->pszSound)) == 0)
00352         {
00353             if ((hmmio = get_mmioFromFile(wps->pszSound)) == 0)
00354             {
00355                 hmmio = get_mmioFromProfile(wps->fdwSound, wps->pszSound);
00356             }
00357         }
00358     }
00359     if (hmmio == 0) goto errCleanUp;
00360 
00361     if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0))
00362     goto errCleanUp;
00363 
00364     TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n",
00365       (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize);
00366 
00367     if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
00368     (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
00369     goto errCleanUp;
00370 
00371     mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
00372     if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
00373     goto errCleanUp;
00374 
00375     TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
00376       (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);
00377 
00378     lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
00379     if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < sizeof(PCMWAVEFORMAT))
00380     goto errCleanUp;
00381 
00382     TRACE("wFormatTag=%04X !\n",    lpWaveFormat->wFormatTag);
00383     TRACE("nChannels=%d\n",         lpWaveFormat->nChannels);
00384     TRACE("nSamplesPerSec=%d\n",    lpWaveFormat->nSamplesPerSec);
00385     TRACE("nAvgBytesPerSec=%d\n",   lpWaveFormat->nAvgBytesPerSec);
00386     TRACE("nBlockAlign=%d\n",       lpWaveFormat->nBlockAlign);
00387     TRACE("wBitsPerSample=%u !\n",  lpWaveFormat->wBitsPerSample);
00388 
00389     /* move to end of 'fmt ' chunk */
00390     mmioAscend(hmmio, &mmckInfo, 0);
00391 
00392     mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
00393     if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
00394     goto errCleanUp;
00395 
00396     TRACE("Chunk Found ckid=%.4s fccType=%08x cksize=%08X\n",
00397       (LPSTR)&mmckInfo.ckid, mmckInfo.fccType, mmckInfo.cksize);
00398 
00399     s.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
00400 
00401     if (waveOutOpen(&wps->hWave, WAVE_MAPPER, lpWaveFormat, (DWORD_PTR)PlaySound_Callback,
00402             (DWORD_PTR)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
00403     goto errCleanUp;
00404 
00405     /* make it so that 3 buffers per second are needed */
00406     bufsize = (((lpWaveFormat->nAvgBytesPerSec / 3) - 1) / lpWaveFormat->nBlockAlign + 1) *
00407     lpWaveFormat->nBlockAlign;
00408     waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
00409     waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
00410     waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
00411     waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
00412     waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
00413     waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
00414     waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
00415     if (waveOutPrepareHeader(wps->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
00416     waveOutPrepareHeader(wps->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
00417     goto errCleanUp;
00418     }
00419 
00420     s.dwEventCount = 1L; /* for first buffer */
00421     index = 0;
00422 
00423     do {
00424     left = mmckInfo.cksize;
00425 
00426     mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET);
00427     while (left)
00428         {
00429         if (WaitForSingleObject(psStopEvent, 0) == WAIT_OBJECT_0)
00430             {
00431         wps->bLoop = FALSE;
00432         break;
00433         }
00434         count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left));
00435         if (count < 1) break;
00436         left -= count;
00437         waveHdr[index].dwBufferLength = count;
00438         waveHdr[index].dwFlags &= ~WHDR_DONE;
00439         if (waveOutWrite(wps->hWave, &waveHdr[index], sizeof(WAVEHDR)) == MMSYSERR_NOERROR) {
00440                 index ^= 1;
00441                 PlaySound_WaitDone(&s);
00442             }
00443             else FIXME("Couldn't play header\n");
00444     }
00445     bRet = TRUE;
00446     } while (wps->bLoop);
00447 
00448     PlaySound_WaitDone(&s); /* for last buffer */
00449     waveOutReset(wps->hWave);
00450 
00451     waveOutUnprepareHeader(wps->hWave, &waveHdr[0], sizeof(WAVEHDR));
00452     waveOutUnprepareHeader(wps->hWave, &waveHdr[1], sizeof(WAVEHDR));
00453 
00454 errCleanUp:
00455     TRACE("Done playing=%s => %s!\n", debugstr_w(wps->pszSound), bRet ? "ok" : "ko");
00456     CloseHandle(s.hEvent);
00457     HeapFree(GetProcessHeap(), 0, waveHdr);
00458     HeapFree(GetProcessHeap(), 0, lpWaveFormat);
00459     if (wps->hWave) while (waveOutClose(wps->hWave) == WAVERR_STILLPLAYING) Sleep(100);
00460     if (hmmio)      mmioClose(hmmio, 0);
00461 
00462     PlaySound_Free(wps);
00463 
00464     return bRet;
00465 }
00466 
00467 static BOOL MULTIMEDIA_PlaySound(const void* pszSound, HMODULE hmod, DWORD fdwSound, BOOL bUnicode)
00468 {
00469     WINE_PLAYSOUND*     wps = NULL;
00470 
00471     TRACE("pszSound='%p' hmod=%p fdwSound=%08X\n",
00472       pszSound, hmod, fdwSound);
00473 
00474     /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
00475      * there could be one if several sounds can be played at once...
00476      */
00477     if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySoundList != NULL)
00478     return FALSE;
00479 
00480     /* alloc internal structure, if we need to play something */
00481     if (pszSound && !(fdwSound & SND_PURGE))
00482     {
00483         if (!(wps = PlaySound_Alloc(pszSound, hmod, fdwSound, bUnicode)))
00484             return FALSE;
00485     }
00486 
00487     EnterCriticalSection(&WINMM_cs);
00488     /* since several threads can enter PlaySound in parallel, we're not
00489      * sure, at this point, that another thread didn't start a new playsound
00490      */
00491     while (PlaySoundList != NULL)
00492     {
00493         ResetEvent(psLastEvent);
00494         /* FIXME: doc says we have to stop all instances of pszSound if it's non
00495          * NULL... as of today, we stop all playing instances */
00496         SetEvent(psStopEvent);
00497 
00498         waveOutReset(PlaySoundList->hWave);
00499         LeaveCriticalSection(&WINMM_cs);
00500         WaitForSingleObject(psLastEvent, INFINITE);
00501         EnterCriticalSection(&WINMM_cs);
00502 
00503         ResetEvent(psStopEvent);
00504     }
00505 
00506     if (wps) wps->lpNext = PlaySoundList;
00507     PlaySoundList = wps;
00508     LeaveCriticalSection(&WINMM_cs);
00509 
00510     if (!pszSound || (fdwSound & SND_PURGE)) return TRUE;
00511 
00512     if (fdwSound & SND_ASYNC)
00513     {
00514         DWORD       id;
00515         HANDLE      handle;
00516         wps->bLoop = (fdwSound & SND_LOOP) ? TRUE : FALSE;
00517         if ((handle = CreateThread(NULL, 0, proc_PlaySound, wps, 0, &id)) != 0) {
00518             wps->hThread = handle;
00519             SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
00520             return TRUE;
00521         }
00522     }
00523     else return proc_PlaySound(wps);
00524 
00525     /* error cases */
00526     PlaySound_Free(wps);
00527     return FALSE;
00528 }
00529 
00530 /**************************************************************************
00531  *              PlaySoundA      [WINMM.@]
00532  */
00533 BOOL WINAPI PlaySoundA(LPCSTR pszSoundA, HMODULE hmod, DWORD fdwSound)
00534 {
00535     return MULTIMEDIA_PlaySound(pszSoundA, hmod, fdwSound, FALSE);
00536 }
00537 
00538 /**************************************************************************
00539  *              PlaySoundW      [WINMM.@]
00540  */
00541 BOOL WINAPI PlaySoundW(LPCWSTR pszSoundW, HMODULE hmod, DWORD fdwSound)
00542 {
00543     return MULTIMEDIA_PlaySound(pszSoundW, hmod, fdwSound, TRUE);
00544 }
00545 
00546 /**************************************************************************
00547  *              sndPlaySoundA       [WINMM.@]
00548  */
00549 BOOL WINAPI sndPlaySoundA(LPCSTR pszSoundA, UINT uFlags)
00550 {
00551     uFlags &= SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC;
00552     return MULTIMEDIA_PlaySound(pszSoundA, 0, uFlags, FALSE);
00553 }
00554 
00555 /**************************************************************************
00556  *              sndPlaySoundW       [WINMM.@]
00557  */
00558 BOOL WINAPI sndPlaySoundW(LPCWSTR pszSound, UINT uFlags)
00559 {
00560     uFlags &= SND_ASYNC|SND_LOOP|SND_MEMORY|SND_NODEFAULT|SND_NOSTOP|SND_SYNC;
00561     return MULTIMEDIA_PlaySound(pszSound, 0, uFlags, TRUE);
00562 }
00563 
00564 /**************************************************************************
00565  *              mmsystemGetVersion  [WINMM.@]
00566  */
00567 UINT WINAPI mmsystemGetVersion(void)
00568 {
00569     TRACE("3.10 (Win95?)\n");
00570     return 0x030a;
00571 }

Generated on Sun May 27 2012 04:26:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.