Changeset 5364 for trunk/src


Ignore:
Timestamp:
Mar 24, 2001, 2:23:48 PM (24 years ago)
Author:
sandervl
Message:

ported Wine's (snd)PlaySoundA/W + fixed mmsystemGetVersion

Location:
trunk/src/winmm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/winmm/playsound.cpp

    r3473 r5364  
    1 /* $Id: playsound.cpp,v 1.6 2000-05-02 13:29:59 bird Exp $ */
     1/* $Id: playsound.cpp,v 1.7 2001-03-24 13:23:48 sandervl Exp $ */
    22
    33/*
    4  * Playsound stubs
    5  *
    6  * Copyright 1998 Joel Troster
    7  *
     4 * Playsound implementation
     5 *
     6 * Wine port (winmm\mmsystem.c)
     7 *
     8 * Copyright 1993 Martin Ayotte
     9 *                Eric POUECH
    810 *
    911 * Project Odin Software License can be found in LICENSE.TXT
     
    1618 ****************************************************************************/
    1719
    18 #define  INCL_BASE
    19 #define  INCL_OS2MM
    20 #include <os2wrap.h>       //Odin32 OS/2 api wrappers
     20#include <os2win.h>
    2121#include <odinwrap.h>
    22 #include <win32type.h>
    23 #include <winconst.h>
     22#include <mmsystem.h>
     23#include <heapstring.h>
    2424#include <misc.h>
     25#include <string.h>
     26#include <win\debugtools.h>
    2527
    2628#define DBG_LOCALLOG    DBG_playsound
    2729#include "dbglocal.h"
    2830
    29 //kso: dirty fix to make this compile! not permanent!
    30 BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *);
    31 #define LowPart u.LowPart
    32 
    33 
    3431ODINDEBUGCHANNEL(WINMM-PLAYSOUND)
     32
     33
     34static HANDLE           PlaySound_hThread = 0;
     35static HANDLE           PlaySound_hPlayEvent = 0;
     36static HANDLE           PlaySound_hReadyEvent = 0;
     37static HANDLE           PlaySound_hMiddleEvent = 0;
     38static BOOL             PlaySound_Result = FALSE;
     39static int              PlaySound_Stop = FALSE;
     40static int              PlaySound_Playing = FALSE;
     41
     42static LPCSTR           PlaySound_pszSound = NULL;
     43static HMODULE          PlaySound_hmod = 0;
     44static DWORD            PlaySound_fdwSound = 0;
     45static int              PlaySound_Loop = FALSE;
     46static int              PlaySound_SearchMode = 0; /* 1 - sndPlaySound search order
     47                                                     2 - PlaySound order */
     48
     49static HMMIO    get_mmioFromFile(LPCSTR lpszName)
     50{
     51    return mmioOpenA((LPSTR)lpszName, NULL,
     52                     MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
     53}
     54
     55static HMMIO    get_mmioFromProfile(UINT uFlags, LPCSTR lpszName)
     56{
     57    char        str[128];
     58    LPSTR       ptr;
     59    HMMIO       hmmio;
     60   
     61    TRACE("searching in SystemSound List !\n");
     62    GetProfileStringA("Sounds", (LPSTR)lpszName, "", str, sizeof(str));
     63    if (strlen(str) == 0) {
     64        if (uFlags & SND_NODEFAULT) return 0;
     65        GetProfileStringA("Sounds", "Default", "", str, sizeof(str));
     66        if (strlen(str) == 0) return 0;
     67    }
     68    if ((ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0';
     69    hmmio = get_mmioFromFile(str);
     70    if (hmmio == 0) {
     71        WARN("can't find SystemSound='%s' !\n", str);
     72        return 0;
     73    }
     74    return hmmio;
     75}
     76
     77struct playsound_data {
     78    HANDLE      hEvent;
     79    DWORD       dwEventCount;
     80};
     81
     82static void CALLBACK PlaySound_Callback(HWAVEOUT hwo, UINT uMsg,
     83                                        DWORD dwInstance, 
     84                                        DWORD dwParam1, DWORD dwParam2)
     85{
     86    struct playsound_data*      s = (struct playsound_data*)dwInstance;
     87
     88    switch (uMsg) {
     89    case WOM_OPEN:
     90    case WOM_CLOSE:
     91        break;
     92    case WOM_DONE:
     93        InterlockedIncrement((LPLONG)&s->dwEventCount);
     94        TRACE("Returning waveHdr=%lx\n", dwParam1);
     95        SetEvent(s->hEvent);
     96        break;
     97    default:
     98        ERR("Unknown uMsg=%d\n", uMsg);
     99    }
     100}
     101
     102static void PlaySound_WaitDone(struct playsound_data* s)
     103{
     104    for (;;) {
     105        ResetEvent(s->hEvent);
     106        if (InterlockedDecrement((LPLONG)&s->dwEventCount) >= 0) {
     107            break;
     108        }
     109        InterlockedIncrement((LPLONG)&s->dwEventCount);
     110       
     111        WaitForSingleObject(s->hEvent, INFINITE);
     112    }
     113}
     114
     115static BOOL WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT uFlags)
     116{
     117    BOOL                bRet = FALSE;
     118    HMMIO               hmmio = 0;
     119    MMCKINFO            ckMainRIFF;
     120    MMCKINFO            mmckInfo;
     121    LPWAVEFORMATEX      lpWaveFormat = NULL;
     122    HWAVE               hWave = 0;
     123    LPWAVEHDR           waveHdr = NULL;
     124    INT                 count, bufsize, left, index;
     125    struct playsound_data       s;
     126
     127    s.hEvent = 0;
     128
     129    TRACE("SoundName='%s' uFlags=%04X !\n", lpszSoundName, uFlags);
     130    if (lpszSoundName == NULL) {
     131        TRACE("Stop !\n");
     132        return FALSE;
     133    }
     134    if (uFlags & SND_MEMORY) {
     135        MMIOINFO        mminfo;
     136        memset(&mminfo, 0, sizeof(mminfo));
     137        mminfo.fccIOProc = FOURCC_MEM;
     138        mminfo.pchBuffer = (LPSTR)lpszSoundName;
     139        mminfo.cchBuffer = -1;
     140        TRACE("Memory sound %p\n", lpszSoundName);
     141        hmmio = mmioOpenA(NULL, &mminfo, MMIO_READ);
     142    } else {
     143        hmmio = 0;
     144        if (uFlags & SND_ALIAS)
     145            if ((hmmio = get_mmioFromProfile(uFlags, lpszSoundName)) == 0)
     146                return FALSE;
     147       
     148        if (uFlags & SND_FILENAME)
     149            if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0) return FALSE;
     150       
     151        if (PlaySound_SearchMode == 1) {
     152            PlaySound_SearchMode = 0;
     153            if ((hmmio = get_mmioFromFile(lpszSoundName)) == 0)
     154                hmmio = get_mmioFromProfile(uFlags, lpszSoundName);
     155        }
     156       
     157        if (PlaySound_SearchMode == 2) {
     158            PlaySound_SearchMode = 0;
     159            if ((hmmio = get_mmioFromProfile(uFlags | SND_NODEFAULT, lpszSoundName)) == 0)
     160                if ((hmmio = get_mmioFromFile(lpszSoundName)) == 0)     
     161                    hmmio = get_mmioFromProfile(uFlags, lpszSoundName);
     162        }
     163    }
     164    if (hmmio == 0) return FALSE;
     165
     166    if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0))
     167        goto errCleanUp;
     168
     169    TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
     170          (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize);
     171
     172    if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
     173        (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
     174        goto errCleanUp;
     175
     176    mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
     177    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
     178        goto errCleanUp;
     179
     180    TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
     181          (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
     182
     183    lpWaveFormat = (WAVEFORMATEX*)HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
     184    if (mmioRead(hmmio, (HPSTR)lpWaveFormat, mmckInfo.cksize) < sizeof(WAVEFORMAT))
     185        goto errCleanUp;
     186
     187    TRACE("wFormatTag=%04X !\n",        lpWaveFormat->wFormatTag);
     188    TRACE("nChannels=%d \n",            lpWaveFormat->nChannels);
     189    TRACE("nSamplesPerSec=%ld\n",       lpWaveFormat->nSamplesPerSec);
     190    TRACE("nAvgBytesPerSec=%ld\n",      lpWaveFormat->nAvgBytesPerSec);
     191    TRACE("nBlockAlign=%d \n",          lpWaveFormat->nBlockAlign);
     192    TRACE("wBitsPerSample=%u !\n",      lpWaveFormat->wBitsPerSample);
     193
     194    /* move to end of 'fmt ' chunk */
     195    mmioAscend(hmmio, &mmckInfo, 0);
     196
     197    mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
     198    if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK))
     199        goto errCleanUp;
     200
     201    TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX\n",
     202          (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
     203
     204    s.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     205
     206    if (waveOutOpen(&hWave, WAVE_MAPPER, lpWaveFormat, (DWORD)PlaySound_Callback,
     207                    (DWORD)&s, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
     208        goto errCleanUp;
     209
     210    /* make it so that 3 buffers per second are needed */
     211    bufsize = (((lpWaveFormat->nAvgBytesPerSec / 3) - 1) / lpWaveFormat->nBlockAlign + 1) *
     212        lpWaveFormat->nBlockAlign;
     213    waveHdr = (LPWAVEHDR)HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
     214    waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
     215    waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
     216    waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
     217    waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
     218    waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
     219    waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
     220    if (waveOutPrepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
     221        waveOutPrepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR))) {
     222        goto errCleanUp;
     223    }
     224
     225    do {
     226        index = 0;
     227        left = mmckInfo.cksize;
     228        s.dwEventCount = 1L; /* for first buffer */
     229
     230        mmioSeek(hmmio, mmckInfo.dwDataOffset, SEEK_SET);
     231        while (left) {
     232            if (PlaySound_Stop) {
     233                PlaySound_Stop = PlaySound_Loop = FALSE;
     234                break;
     235            }
     236            count = mmioRead(hmmio, waveHdr[index].lpData, min(bufsize, left));
     237            if (count < 1) break;
     238            left -= count;
     239            waveHdr[index].dwBufferLength = count;
     240            waveHdr[index].dwFlags &= ~WHDR_DONE;
     241            waveOutWrite(hWave, &waveHdr[index], sizeof(WAVEHDR));
     242            index ^= 1;
     243            PlaySound_WaitDone(&s);
     244        }
     245        bRet = TRUE;
     246    } while (PlaySound_Loop);
     247
     248    PlaySound_WaitDone(&s);
     249    waveOutReset(hWave);
     250
     251    waveOutUnprepareHeader(hWave, &waveHdr[0], sizeof(WAVEHDR));
     252    waveOutUnprepareHeader(hWave, &waveHdr[1], sizeof(WAVEHDR));
     253
     254errCleanUp:
     255    CloseHandle(s.hEvent);
     256    HeapFree(GetProcessHeap(), 0, waveHdr);
     257    HeapFree(GetProcessHeap(), 0, lpWaveFormat);
     258    if (hWave)          while (waveOutClose(hWave) == WAVERR_STILLPLAYING) Sleep(100);
     259    if (hmmio)          mmioClose(hmmio, 0);
     260
     261    return bRet;
     262}
     263
     264static DWORD WINAPI PlaySound_Thread(LPVOID arg)
     265{
     266    DWORD     res;
     267   
     268    for (;;) {
     269        PlaySound_Playing = FALSE;
     270        SetEvent(PlaySound_hReadyEvent);
     271        res = WaitForSingleObject(PlaySound_hPlayEvent, INFINITE);
     272        ResetEvent(PlaySound_hReadyEvent);
     273        SetEvent(PlaySound_hMiddleEvent);
     274        if (res == WAIT_FAILED) ExitThread(2);
     275        if (res != WAIT_OBJECT_0) continue;
     276        PlaySound_Playing = TRUE;
     277       
     278        if ((PlaySound_fdwSound & SND_RESOURCE) == SND_RESOURCE) {
     279            HRSRC       hRES;
     280            HGLOBAL     hGLOB;
     281            void*       ptr;
     282
     283            if ((hRES = FindResourceA(PlaySound_hmod, PlaySound_pszSound, "WAVE")) == 0) {
     284                PlaySound_Result = FALSE;
     285                continue;
     286            }
     287            if ((hGLOB = LoadResource(PlaySound_hmod, hRES)) == 0) {
     288                PlaySound_Result = FALSE;
     289                continue;
     290            }
     291            if ((ptr = LockResource(hGLOB)) == NULL) {
     292                FreeResource(hGLOB);
     293                PlaySound_Result = FALSE;
     294                continue;
     295            }
     296            PlaySound_Result = proc_PlaySound((LPCSTR)ptr,
     297                                              ((UINT16)PlaySound_fdwSound ^ SND_RESOURCE) | SND_MEMORY);
     298            FreeResource(hGLOB);
     299            continue;
     300        }
     301        PlaySound_Result = proc_PlaySound(PlaySound_pszSound, (UINT16)PlaySound_fdwSound);
     302    }
     303}
    35304
    36305
     
    54323              DWORD, fdwSound)
    55324{
    56   dprintf(("WINMM:PlaySoundA not implemented\n"));
    57   if((fdwSound & (SND_SYNC_W|SND_ASYNC_W)) == (SND_SYNC_W|SND_ASYNC_W)) {
    58 //      SetLastError(ERROR_INVALID_PARAMETER_W);
     325    static LPSTR StrDup = NULL;
     326   
     327    TRACE("pszSound='%p' hmod=%04X fdwSound=%08lX\n",
     328          pszSound, hmod, fdwSound);
     329   
     330    if (PlaySound_hThread == 0) { /* This is the first time they called us */
     331        DWORD   id;
     332        if ((PlaySound_hReadyEvent = CreateEventA(NULL, TRUE, FALSE, NULL)) == 0)
     333            return FALSE;
     334        if ((PlaySound_hMiddleEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
     335            return FALSE;
     336        if ((PlaySound_hPlayEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
     337            return FALSE;
     338        if ((PlaySound_hThread = CreateThread(NULL, 0, PlaySound_Thread, 0, 0, &id)) == 0)
     339            return FALSE;
     340    }
     341   
     342    /* FIXME? I see no difference between SND_WAIT and SND_NOSTOP ! */
     343    if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySound_Playing)
    59344        return FALSE;
    60   }
    61 //  if(fdwSound & (SND_MEMORY_W|SND_ALIAS_W|SND_FILENAME_W|SND_RESOURCE_W) == (SND_SYNC_W|SND_ASYNC_W)) {
    62 //      SetLastError(ERROR_INVALID_PARAMETER_W);
    63 //      return FALSE;
    64 //  }
    65   return(FALSE);
     345   
     346    /* Trying to stop if playing */
     347    if (PlaySound_Playing) PlaySound_Stop = TRUE;
     348   
     349    /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave*/
     350    if (WaitForSingleObject(PlaySound_hReadyEvent, 1000*10) != WAIT_OBJECT_0)
     351        return FALSE;
     352   
     353    if (!pszSound || (fdwSound & SND_PURGE))
     354        return FALSE; /* We stoped playing so leaving */
     355   
     356    if (PlaySound_SearchMode != 1) PlaySound_SearchMode = 2;
     357    if (!(fdwSound & SND_ASYNC)) {
     358        if (fdwSound & SND_LOOP)
     359            return FALSE;
     360        PlaySound_pszSound = pszSound;
     361        PlaySound_hmod = hmod;
     362        PlaySound_fdwSound = fdwSound;
     363        PlaySound_Result = FALSE;
     364        SetEvent(PlaySound_hPlayEvent);
     365        if (WaitForSingleObject(PlaySound_hMiddleEvent, INFINITE) != WAIT_OBJECT_0)
     366            return FALSE;
     367        if (WaitForSingleObject(PlaySound_hReadyEvent, INFINITE) != WAIT_OBJECT_0)
     368            return FALSE;
     369        return PlaySound_Result;
     370    } else {
     371        PlaySound_hmod = hmod;
     372        PlaySound_fdwSound = fdwSound;
     373        PlaySound_Result = FALSE;
     374        if (StrDup) {
     375            HeapFree(GetProcessHeap(), 0, StrDup);
     376            StrDup = NULL;
     377        }
     378        if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
     379                                          !((DWORD)pszSound >> 16)) || !pszSound)) {
     380            StrDup = HEAP_strdupA(GetProcessHeap(), 0,pszSound);
     381            PlaySound_pszSound = StrDup;
     382        } else PlaySound_pszSound = pszSound;
     383        PlaySound_Loop = fdwSound & SND_LOOP;
     384        SetEvent(PlaySound_hPlayEvent);
     385        ResetEvent(PlaySound_hMiddleEvent);
     386        return TRUE;
     387    }
     388    return FALSE;
    66389}
    67390
     
    86409              DWORD, fdwSound)
    87410{
    88   dprintf(("WINMM:PlaySoundW not implemented\n"));
    89   return(FALSE);
     411    LPSTR       pszSoundA;
     412    BOOL        bSound;
     413   
     414    if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
     415                                      !((DWORD)pszSound >> 16)) || !pszSound)) {
     416        pszSoundA = HEAP_strdupWtoA(GetProcessHeap(), 0,pszSound);
     417        bSound = PlaySoundA(pszSoundA, hmod, fdwSound);
     418        HeapFree(GetProcessHeap(), 0, pszSoundA);
     419    } else 
     420        bSound = PlaySoundA((LPCSTR)pszSound, hmod, fdwSound);
     421   
     422    return bSound;
    90423}
    91424
     
    104437
    105438ODINFUNCTION2(BOOL, sndPlaySoundA,
    106               LPCSTR, pszSound,
    107               UINT, fuSound)
    108 {
    109   dprintf(("WINMM:sndPlaySoundA not implemented\n"));
    110   return(FALSE);
     439              LPCSTR, lpszSoundName,
     440              UINT, uFlags)
     441{
     442    PlaySound_SearchMode = 1;
     443    return PlaySoundA(lpszSoundName, 0, uFlags);
    111444}
    112445
     
    126459
    127460ODINFUNCTION2(BOOL, sndPlaySoundW,
    128               LPCWSTR, pszSound,
    129               UINT, fuSound)
    130 {
    131   dprintf(("WINMM:sndPlaySoundW not implemented\n"));
    132   return(FALSE);
    133 }
    134 
     461              LPCWSTR, lpszSoundName,
     462              UINT, uFlags)
     463{
     464    PlaySound_SearchMode = 1;
     465    return PlaySoundW(lpszSoundName, 0, uFlags);
     466}
     467
  • trunk/src/winmm/time.cpp

    r5348 r5364  
    1 /* $Id: time.cpp,v 1.10 2001-03-21 12:33:22 sandervl Exp $ */
     1/* $Id: time.cpp,v 1.11 2001-03-24 13:23:48 sandervl Exp $ */
    22
    33/*
     
    2828
    2929
    30 
    3130/*****************************************************************************
    3231 * Name      : mmsystemGetVersion
     
    4443ODINFUNCTION0(UINT, mmsystemGetVersion)
    4544{
    46   return 4;
    47 }
    48 
     45  //Returned by winmm.dll from NT4, SP6
     46  return 0x030A;
     47}
    4948
    5049/*****************************************************************************
Note: See TracChangeset for help on using the changeset viewer.