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

primary.c
Go to the documentation of this file.
00001 /*              DirectSound
00002  *
00003  * Copyright 1998 Marcus Meissner
00004  * Copyright 1998 Rob Riggs
00005  * Copyright 2000-2002 TransGaming Technologies, Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 
00024 #define NONAMELESSSTRUCT
00025 #define NONAMELESSUNION
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "mmsystem.h"
00030 #include "winternl.h"
00031 #include "mmddk.h"
00032 #include "wine/debug.h"
00033 #include "dsound.h"
00034 #include "dsdriver.h"
00035 #include "dsound_private.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
00038 
00047 DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign)
00048 {
00049     /* Given a timer delay of 10ms, the fragment size is approximately:
00050      *     fraglen = (nSamplesPerSec * 10 / 1000) * nBlockAlign
00051      * ==> fraglen = (nSamplesPerSec / 100) * nBlockSize
00052      *
00053      * ALSA uses buffers that are powers of 2. Because of this, fraglen
00054      * is rounded up to the nearest power of 2:
00055      */
00056 
00057     if (nSamplesPerSec <= 12800)
00058         return 128 * nBlockAlign;
00059 
00060     if (nSamplesPerSec <= 25600)
00061         return 256 * nBlockAlign;
00062 
00063     if (nSamplesPerSec <= 51200)
00064         return 512 * nBlockAlign;
00065 
00066     return 1024 * nBlockAlign;
00067 }
00068 
00069 static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
00070 {
00071     TRACE("(%p)\n", device);
00072 
00073     device->fraglen = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
00074     device->helfrags = device->buflen / device->fraglen;
00075     TRACE("fraglen=%d helfrags=%d\n", device->fraglen, device->helfrags);
00076 
00077     if (device->hwbuf && device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD)
00078         device->writelead = 0;
00079     else
00080         /* calculate the 10ms write lead */
00081         device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign;
00082 }
00083 
00084 HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
00085 {
00086     HRESULT hres = DS_OK;
00087     TRACE("(%p, %d)\n", device, forcewave);
00088 
00089     if (device->driver)
00090     {
00091         IDsDriver_Close(device->driver);
00092         if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
00093             waveOutClose(device->hwo);
00094         IDsDriver_Release(device->driver);
00095         device->driver = NULL;
00096         device->buffer = NULL;
00097         device->hwo = 0;
00098     }
00099     else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
00100         waveOutClose(device->hwo);
00101 
00102     /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
00103     if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave)
00104         waveOutMessage((HWAVEOUT)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
00105 
00106     /* Get driver description */
00107     if (device->driver) {
00108         DWORD wod = device->drvdesc.dnDevNode;
00109         hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
00110         device->drvdesc.dnDevNode = wod;
00111         if (FAILED(hres)) {
00112             WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres);
00113             IDsDriver_Release(device->driver);
00114             device->driver = NULL;
00115         }
00116         }
00117 
00118         /* if no DirectSound interface available, use WINMM API instead */
00119     if (!device->driver)
00120         device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
00121 
00122     if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
00123     {
00124         DWORD flags = CALLBACK_FUNCTION;
00125 
00126         if (device->driver)
00127             flags |= WAVE_DIRECTSOUND;
00128 
00129         hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD_PTR)device, flags));
00130         if (FAILED(hres)) {
00131             WARN("waveOutOpen failed\n");
00132             if (device->driver)
00133             {
00134                 IDsDriver_Release(device->driver);
00135                 device->driver = NULL;
00136             }
00137             return hres;
00138         }
00139     }
00140 
00141     if (device->driver)
00142         hres = IDsDriver_Open(device->driver);
00143 
00144     return hres;
00145 }
00146 
00147 static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
00148 {
00149     DWORD buflen;
00150     HRESULT err = DS_OK;
00151     TRACE("(%p)\n", device);
00152 
00153     /* on original windows, the buffer it set to a fixed size, no matter what the settings are.
00154        on windows this size is always fixed (tested on win-xp) */
00155     if (!device->buflen)
00156         device->buflen = ds_hel_buflen;
00157     buflen = device->buflen;
00158     buflen -= buflen % device->pwfx->nBlockAlign;
00159     device->buflen = buflen;
00160 
00161     if (device->driver)
00162     {
00163         err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
00164                           DSBCAPS_PRIMARYBUFFER,0,
00165                           &(device->buflen),&(device->buffer),
00166                           (LPVOID*)&(device->hwbuf));
00167 
00168         if (err != DS_OK) {
00169             WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
00170             err = DSOUND_ReopenDevice(device, TRUE);
00171             if (FAILED(err))
00172             {
00173                 WARN("Falling back to waveout failed too! Giving up\n");
00174                 return err;
00175             }
00176         }
00177                 if (device->hwbuf)
00178                     IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
00179 
00180                 DSOUND_RecalcPrimary(device);
00181         device->prebuf = ds_snd_queue_max;
00182         if (device->helfrags < ds_snd_queue_min)
00183         {
00184             WARN("Too little sound buffer to be effective (%d/%d) falling back to waveout\n", device->buflen, ds_snd_queue_min * device->fraglen);
00185             device->buflen = buflen;
00186             IDsDriverBuffer_Release(device->hwbuf);
00187             device->hwbuf = NULL;
00188             err = DSOUND_ReopenDevice(device, TRUE);
00189             if (FAILED(err))
00190             {
00191                 WARN("Falling back to waveout failed too! Giving up\n");
00192                 return err;
00193             }
00194         }
00195         else if (device->helfrags < ds_snd_queue_max)
00196             device->prebuf = device->helfrags;
00197     }
00198 
00199     device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
00200     device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len);
00201     if (!device->mix_buffer)
00202     {
00203         if (device->hwbuf)
00204             IDsDriverBuffer_Release(device->hwbuf);
00205         device->hwbuf = NULL;
00206         return DSERR_OUTOFMEMORY;
00207     }
00208 
00209     if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
00210     else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
00211 
00212     /* are we using waveOut stuff? */
00213     if (!device->driver) {
00214         LPBYTE newbuf;
00215         LPWAVEHDR headers = NULL;
00216         DWORD overshot;
00217         unsigned int c;
00218 
00219         /* Start in pause mode, to allow buffers to get filled */
00220         waveOutPause(device->hwo);
00221 
00222         TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
00223 
00224         /* reallocate emulated primary buffer */
00225         if (device->buffer)
00226             newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen);
00227         else
00228             newbuf = HeapAlloc(GetProcessHeap(),0, buflen);
00229 
00230         if (!newbuf) {
00231             ERR("failed to allocate primary buffer\n");
00232             return DSERR_OUTOFMEMORY;
00233             /* but the old buffer might still exist and must be re-prepared */
00234         }
00235 
00236         DSOUND_RecalcPrimary(device);
00237         if (device->pwave)
00238             headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR));
00239         else
00240             headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR));
00241 
00242         if (!headers) {
00243             ERR("failed to allocate wave headers\n");
00244             HeapFree(GetProcessHeap(), 0, newbuf);
00245             DSOUND_RecalcPrimary(device);
00246             return DSERR_OUTOFMEMORY;
00247         }
00248 
00249         device->buffer = newbuf;
00250         device->pwave = headers;
00251 
00252         /* prepare fragment headers */
00253         for (c=0; c<device->helfrags; c++) {
00254             device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen;
00255             device->pwave[c].dwBufferLength = device->fraglen;
00256             device->pwave[c].dwUser = (DWORD_PTR)device;
00257             device->pwave[c].dwFlags = 0;
00258             device->pwave[c].dwLoops = 0;
00259             err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)));
00260             if (err != DS_OK) {
00261                 while (c--)
00262                     waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR));
00263                 break;
00264             }
00265         }
00266 
00267         overshot = device->buflen % device->fraglen;
00268         /* sanity */
00269         if(overshot)
00270         {
00271             overshot -= overshot % device->pwfx->nBlockAlign;
00272             device->pwave[device->helfrags - 1].dwBufferLength += overshot;
00273         }
00274 
00275         TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot);
00276     }
00277     device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
00278     device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
00279     FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
00280     FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
00281     device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
00282     return err;
00283 }
00284 
00285 
00286 static void DSOUND_PrimaryClose(DirectSoundDevice *device)
00287 {
00288     TRACE("(%p)\n", device);
00289 
00290     /* are we using waveOut stuff? */
00291     if (!device->hwbuf) {
00292         unsigned c;
00293 
00294         /* get out of CS when calling the wave system */
00295         LeaveCriticalSection(&(device->mixlock));
00296         /* **** */
00297         device->pwqueue = (DWORD)-1; /* resetting queues */
00298         waveOutReset(device->hwo);
00299         for (c=0; c<device->helfrags; c++)
00300             waveOutUnprepareHeader(device->hwo, &device->pwave[c], sizeof(WAVEHDR));
00301         /* **** */
00302         EnterCriticalSection(&(device->mixlock));
00303 
00304         /* clear the queue */
00305         device->pwqueue = 0;
00306     } else {
00307         ULONG ref = IDsDriverBuffer_Release(device->hwbuf);
00308         if (!ref)
00309             device->hwbuf = 0;
00310         else
00311             ERR("Still %d references on primary buffer, refcount leak?\n", ref);
00312     }
00313 }
00314 
00315 HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
00316 {
00317     HRESULT err = DS_OK;
00318     TRACE("(%p)\n", device);
00319 
00320     device->buflen = ds_hel_buflen;
00321     err = DSOUND_PrimaryOpen(device);
00322 
00323     if (err != DS_OK) {
00324         WARN("DSOUND_PrimaryOpen failed\n");
00325         return err;
00326     }
00327 
00328     device->state = STATE_STOPPED;
00329     return DS_OK;
00330 }
00331 
00332 HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
00333 {
00334     TRACE("(%p)\n", device);
00335 
00336     /* **** */
00337     EnterCriticalSection(&(device->mixlock));
00338 
00339     DSOUND_PrimaryClose(device);
00340     if (device->driver) {
00341         if (device->hwbuf) {
00342             if (IDsDriverBuffer_Release(device->hwbuf) == 0)
00343                 device->hwbuf = 0;
00344         }
00345     } else
00346                 HeapFree(GetProcessHeap(),0,device->pwave);
00347         HeapFree(GetProcessHeap(),0,device->pwfx);
00348         device->pwfx=NULL;
00349 
00350     LeaveCriticalSection(&(device->mixlock));
00351     /* **** */
00352 
00353     return DS_OK;
00354 }
00355 
00356 HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
00357 {
00358     HRESULT err = DS_OK;
00359     TRACE("(%p)\n", device);
00360 
00361     if (device->hwbuf) {
00362         err = IDsDriverBuffer_Play(device->hwbuf, 0, 0, DSBPLAY_LOOPING);
00363         if (err != DS_OK)
00364             WARN("IDsDriverBuffer_Play failed\n");
00365     } else {
00366         err = mmErr(waveOutRestart(device->hwo));
00367         if (err != DS_OK)
00368             WARN("waveOutRestart failed\n");
00369     }
00370 
00371     return err;
00372 }
00373 
00374 HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
00375 {
00376     HRESULT err = DS_OK;
00377     TRACE("(%p)\n", device);
00378 
00379     if (device->hwbuf) {
00380         err = IDsDriverBuffer_Stop(device->hwbuf);
00381         if (err == DSERR_BUFFERLOST) {
00382             DSOUND_PrimaryClose(device);
00383             err = DSOUND_ReopenDevice(device, FALSE);
00384             if (FAILED(err))
00385                 ERR("DSOUND_ReopenDevice failed\n");
00386             else
00387             {
00388                 err = DSOUND_PrimaryOpen(device);
00389                 if (FAILED(err))
00390                     WARN("DSOUND_PrimaryOpen failed\n");
00391             }
00392         } else if (err != DS_OK) {
00393             WARN("IDsDriverBuffer_Stop failed\n");
00394         }
00395     } else {
00396 
00397         /* don't call the wave system with the lock set */
00398         LeaveCriticalSection(&(device->mixlock));
00399         /* **** */
00400 
00401         err = mmErr(waveOutPause(device->hwo));
00402 
00403         /* **** */
00404         EnterCriticalSection(&(device->mixlock));
00405 
00406         if (err != DS_OK)
00407             WARN("waveOutPause failed\n");
00408     }
00409 
00410     return err;
00411 }
00412 
00413 HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos)
00414 {
00415     TRACE("(%p,%p,%p)\n", device, playpos, writepos);
00416 
00417     if (device->hwbuf) {
00418         HRESULT err=IDsDriverBuffer_GetPosition(device->hwbuf,playpos,writepos);
00419         if (err != S_OK) {
00420             WARN("IDsDriverBuffer_GetPosition failed\n");
00421             return err;
00422         }
00423     } else {
00424         TRACE("pwplay=%i, pwqueue=%i\n", device->pwplay, device->pwqueue);
00425 
00426         /* check if playpos was requested */
00427         if (playpos)
00428             /* use the cached play position */
00429             *playpos = device->pwplay * device->fraglen;
00430 
00431         /* check if writepos was requested */
00432         if (writepos)
00433             /* the writepos is the first non-queued position */
00434             *writepos = ((device->pwplay + device->pwqueue) % device->helfrags) * device->fraglen;
00435     }
00436     TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:-1, writepos?*writepos:-1, device, GetTickCount());
00437     return DS_OK;
00438 }
00439 
00440 HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced)
00441 {
00442     HRESULT err = DSERR_BUFFERLOST;
00443     int i, alloc_size, cp_size;
00444     DWORD nSamplesPerSec, bpp, chans;
00445     TRACE("(%p,%p)\n", device, wfex);
00446 
00447     if (device->priolevel == DSSCL_NORMAL) {
00448         WARN("failed priority check!\n");
00449         return DSERR_PRIOLEVELNEEDED;
00450     }
00451 
00452     /* Let's be pedantic! */
00453     if (wfex == NULL) {
00454         WARN("invalid parameter: wfex==NULL!\n");
00455         return DSERR_INVALIDPARAM;
00456     }
00457     TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
00458               "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
00459           wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
00460           wfex->nAvgBytesPerSec, wfex->nBlockAlign,
00461           wfex->wBitsPerSample, wfex->cbSize);
00462 
00463     /* **** */
00464     RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
00465     EnterCriticalSection(&(device->mixlock));
00466 
00467         if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
00468             alloc_size = sizeof(WAVEFORMATEX);
00469             cp_size = sizeof(PCMWAVEFORMAT);
00470         } else
00471             alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize;
00472 
00473         device->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,device->pwfx,alloc_size);
00474 
00475     nSamplesPerSec = device->pwfx->nSamplesPerSec;
00476     bpp = device->pwfx->wBitsPerSample;
00477     chans = device->pwfx->nChannels;
00478 
00479         CopyMemory(device->pwfx, wfex, cp_size);
00480 
00481     if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) {
00482         err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx);
00483 
00484         /* On bad format, try to re-create, big chance it will work then, only do this if we <HAVE> to */
00485         if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT))
00486         {
00487             err = DSERR_BUFFERLOST;
00488                 CopyMemory(device->pwfx, wfex, cp_size);
00489         }
00490 
00491         if (err != DSERR_BUFFERLOST && FAILED(err)) {
00492             WARN("IDsDriverBuffer_SetFormat failed\n");
00493             if (!forced)
00494                 err = DS_OK;
00495             goto done;
00496         }
00497 
00498         if (err == S_FALSE)
00499         {
00500             /* ALSA specific: S_FALSE tells that recreation was successful,
00501              * but size and location may be changed, and buffer has to be restarted
00502              * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST
00503              * and the entire re-initialization will occur anyway
00504              */
00505             IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER);
00506             IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0);
00507 
00508             if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
00509             else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
00510             device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
00511             err = DS_OK;
00512         }
00513         DSOUND_RecalcPrimary(device);
00514     }
00515 
00516     if (err == DSERR_BUFFERLOST)
00517     {
00518         DSOUND_PrimaryClose(device);
00519 
00520         err = DSOUND_ReopenDevice(device, FALSE);
00521         if (FAILED(err))
00522         {
00523             WARN("DSOUND_ReopenDevice failed: %08x\n", err);
00524             goto done;
00525         }
00526         err = DSOUND_PrimaryOpen(device);
00527         if (err != DS_OK) {
00528             WARN("DSOUND_PrimaryOpen failed\n");
00529             goto done;
00530         }
00531 
00532         if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer)
00533         {
00534             DSOUND_PrimaryClose(device);
00535             device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec;
00536             err = DSOUND_ReopenDevice(device, TRUE);
00537             if (FAILED(err))
00538                 WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err);
00539             else if (FAILED((err = DSOUND_PrimaryOpen(device))))
00540                 WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err);
00541         }
00542     }
00543 
00544     device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
00545     device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len);
00546     FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
00547     device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
00548     device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
00549 
00550     if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) {
00551         IDirectSoundBufferImpl** dsb = device->buffers;
00552         for (i = 0; i < device->nrofbuffers; i++, dsb++) {
00553             /* **** */
00554             RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE);
00555 
00556             (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
00557             DSOUND_RecalcFormat((*dsb));
00558             DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE);
00559             (*dsb)->primary_mixpos = 0;
00560 
00561             RtlReleaseResource(&(*dsb)->lock);
00562             /* **** */
00563         }
00564     }
00565 
00566 done:
00567     LeaveCriticalSection(&(device->mixlock));
00568     RtlReleaseResource(&(device->buffer_list_lock));
00569     /* **** */
00570 
00571     return err;
00572 }
00573 
00574 /*******************************************************************************
00575  *      PrimaryBuffer
00576  */
00577 /* This sets this format for the <em>Primary Buffer Only</em> */
00578 /* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */
00579 static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
00580     LPDIRECTSOUNDBUFFER iface,
00581     LPCWAVEFORMATEX wfex)
00582 {
00583     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00584     TRACE("(%p,%p)\n", iface, wfex);
00585     return DSOUND_PrimarySetFormat(device, wfex, device->priolevel == DSSCL_WRITEPRIMARY);
00586 }
00587 
00588 static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
00589     LPDIRECTSOUNDBUFFER iface,LONG vol
00590 ) {
00591     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00592     DWORD ampfactors;
00593         HRESULT hres = DS_OK;
00594     TRACE("(%p,%d)\n", iface, vol);
00595 
00596     if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
00597         WARN("control unavailable\n");
00598         return DSERR_CONTROLUNAVAIL;
00599     }
00600 
00601     if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
00602         WARN("invalid parameter: vol = %d\n", vol);
00603         return DSERR_INVALIDPARAM;
00604     }
00605 
00606     /* **** */
00607     EnterCriticalSection(&(device->mixlock));
00608 
00609         waveOutGetVolume(device->hwo, &ampfactors);
00610         device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
00611         device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
00612         DSOUND_AmpFactorToVolPan(&device->volpan);
00613         if (vol != device->volpan.lVolume) {
00614             device->volpan.lVolume=vol;
00615             DSOUND_RecalcVolPan(&device->volpan);
00616             if (device->hwbuf) {
00617                 hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
00618                 if (hres != DS_OK)
00619                     WARN("IDsDriverBuffer_SetVolumePan failed\n");
00620             } else {
00621                 ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
00622                 waveOutSetVolume(device->hwo, ampfactors);
00623             }
00624         }
00625 
00626     LeaveCriticalSection(&(device->mixlock));
00627     /* **** */
00628 
00629     return hres;
00630 }
00631 
00632 static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
00633     LPDIRECTSOUNDBUFFER iface,LPLONG vol
00634 ) {
00635     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00636     DWORD ampfactors;
00637     TRACE("(%p,%p)\n", iface, vol);
00638 
00639     if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
00640         WARN("control unavailable\n");
00641         return DSERR_CONTROLUNAVAIL;
00642     }
00643 
00644     if (vol == NULL) {
00645         WARN("invalid parameter: vol = NULL\n");
00646         return DSERR_INVALIDPARAM;
00647     }
00648 
00649         if (!device->hwbuf)
00650         {
00651         waveOutGetVolume(device->hwo, &ampfactors);
00652         device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
00653         device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
00654         DSOUND_AmpFactorToVolPan(&device->volpan);
00655         }
00656         *vol = device->volpan.lVolume;
00657     return DS_OK;
00658 }
00659 
00660 static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
00661     LPDIRECTSOUNDBUFFER iface,DWORD freq
00662 ) {
00663     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
00664     TRACE("(%p,%d)\n",This,freq);
00665 
00666     /* You cannot set the frequency of the primary buffer */
00667     WARN("control unavailable\n");
00668     return DSERR_CONTROLUNAVAIL;
00669 }
00670 
00671 static HRESULT WINAPI PrimaryBufferImpl_Play(
00672     LPDIRECTSOUNDBUFFER iface,DWORD reserved1,DWORD reserved2,DWORD flags
00673 ) {
00674     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00675     TRACE("(%p,%08x,%08x,%08x)\n", iface, reserved1, reserved2, flags);
00676 
00677     if (!(flags & DSBPLAY_LOOPING)) {
00678         WARN("invalid parameter: flags = %08x\n", flags);
00679         return DSERR_INVALIDPARAM;
00680     }
00681 
00682     /* **** */
00683     EnterCriticalSection(&(device->mixlock));
00684 
00685     if (device->state == STATE_STOPPED)
00686         device->state = STATE_STARTING;
00687     else if (device->state == STATE_STOPPING)
00688         device->state = STATE_PLAYING;
00689 
00690     LeaveCriticalSection(&(device->mixlock));
00691     /* **** */
00692 
00693     return DS_OK;
00694 }
00695 
00696 static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER iface)
00697 {
00698     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00699     TRACE("(%p)\n", iface);
00700 
00701     /* **** */
00702     EnterCriticalSection(&(device->mixlock));
00703 
00704     if (device->state == STATE_PLAYING)
00705         device->state = STATE_STOPPING;
00706     else if (device->state == STATE_STARTING)
00707         device->state = STATE_STOPPED;
00708 
00709     LeaveCriticalSection(&(device->mixlock));
00710     /* **** */
00711 
00712     return DS_OK;
00713 }
00714 
00715 static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER iface)
00716 {
00717     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
00718     ULONG ref = InterlockedIncrement(&(This->ref));
00719     TRACE("(%p) ref was %d\n", This, ref - 1);
00720     return ref;
00721 }
00722 
00723 static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER iface)
00724 {
00725     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
00726     DWORD ref = InterlockedDecrement(&(This->ref));
00727     TRACE("(%p) ref was %d\n", This, ref + 1);
00728 
00729     if (!ref) {
00730         This->device->primary = NULL;
00731         HeapFree(GetProcessHeap(), 0, This);
00732         TRACE("(%p) released\n", This);
00733     }
00734     return ref;
00735 }
00736 
00737 static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(
00738     LPDIRECTSOUNDBUFFER iface,LPDWORD playpos,LPDWORD writepos
00739 ) {
00740     HRESULT hres;
00741         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00742     TRACE("(%p,%p,%p)\n", iface, playpos, writepos);
00743 
00744     /* **** */
00745     EnterCriticalSection(&(device->mixlock));
00746 
00747     hres = DSOUND_PrimaryGetPosition(device, playpos, writepos);
00748     if (hres != DS_OK) {
00749         WARN("DSOUND_PrimaryGetPosition failed\n");
00750         LeaveCriticalSection(&(device->mixlock));
00751         return hres;
00752     }
00753     if (writepos) {
00754         if (device->state != STATE_STOPPED)
00755             /* apply the documented 10ms lead to writepos */
00756             *writepos += device->writelead;
00757         while (*writepos >= device->buflen) *writepos -= device->buflen;
00758     }
00759 
00760     LeaveCriticalSection(&(device->mixlock));
00761     /* **** */
00762 
00763     TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount());
00764     return DS_OK;
00765 }
00766 
00767 static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
00768     LPDIRECTSOUNDBUFFER iface,LPDWORD status
00769 ) {
00770         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00771     TRACE("(%p,%p)\n", iface, status);
00772 
00773     if (status == NULL) {
00774         WARN("invalid parameter: status == NULL\n");
00775         return DSERR_INVALIDPARAM;
00776     }
00777 
00778     *status = 0;
00779     if ((device->state == STATE_STARTING) ||
00780         (device->state == STATE_PLAYING))
00781         *status |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
00782 
00783     TRACE("status=%x\n", *status);
00784     return DS_OK;
00785 }
00786 
00787 
00788 static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
00789     LPDIRECTSOUNDBUFFER iface,
00790     LPWAVEFORMATEX lpwf,
00791     DWORD wfsize,
00792     LPDWORD wfwritten)
00793 {
00794     DWORD size;
00795     DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00796     TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten);
00797 
00798     size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
00799 
00800     if (lpwf) { /* NULL is valid */
00801         if (wfsize >= size) {
00802             CopyMemory(lpwf,device->pwfx,size);
00803             if (wfwritten)
00804                 *wfwritten = size;
00805         } else {
00806             WARN("invalid parameter: wfsize too small\n");
00807             if (wfwritten)
00808                 *wfwritten = 0;
00809             return DSERR_INVALIDPARAM;
00810         }
00811     } else {
00812         if (wfwritten)
00813             *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
00814         else {
00815             WARN("invalid parameter: wfwritten == NULL\n");
00816             return DSERR_INVALIDPARAM;
00817         }
00818     }
00819 
00820     return DS_OK;
00821 }
00822 
00823 static HRESULT WINAPI PrimaryBufferImpl_Lock(
00824     LPDIRECTSOUNDBUFFER iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
00825 ) {
00826     HRESULT hres;
00827         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00828     TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n",
00829         iface,
00830         writecursor,
00831         writebytes,
00832         lplpaudioptr1,
00833         audiobytes1,
00834         lplpaudioptr2,
00835         audiobytes2,
00836         flags,
00837         GetTickCount()
00838     );
00839 
00840         if (!audiobytes1)
00841             return DSERR_INVALIDPARAM;
00842 
00843     if (device->priolevel != DSSCL_WRITEPRIMARY) {
00844         WARN("failed priority check!\n");
00845         return DSERR_PRIOLEVELNEEDED;
00846     }
00847 
00848         /* when this flag is set, writecursor is meaningless and must be calculated */
00849     if (flags & DSBLOCK_FROMWRITECURSOR) {
00850         /* GetCurrentPosition does too much magic to duplicate here */
00851         hres = IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writecursor);
00852         if (hres != DS_OK) {
00853             WARN("IDirectSoundBuffer_GetCurrentPosition failed\n");
00854             return hres;
00855         }
00856     }
00857 
00858         /* when this flag is set, writebytes is meaningless and must be set */
00859     if (flags & DSBLOCK_ENTIREBUFFER)
00860         writebytes = device->buflen;
00861 
00862         if (writecursor >= device->buflen) {
00863                 WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
00864              writecursor, device->buflen);
00865                 return DSERR_INVALIDPARAM;
00866         }
00867 
00868         if (writebytes > device->buflen) {
00869                 WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
00870              writebytes, device->buflen);
00871                 return DSERR_INVALIDPARAM;
00872         }
00873 
00874     if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
00875         hres = IDsDriverBuffer_Lock(device->hwbuf,
00876                         lplpaudioptr1, audiobytes1,
00877                         lplpaudioptr2, audiobytes2,
00878                         writecursor, writebytes,
00879                         0);
00880         if (hres != DS_OK) {
00881             WARN("IDsDriverBuffer_Lock failed\n");
00882             return hres;
00883         }
00884     } else {
00885         if (writecursor+writebytes <= device->buflen) {
00886             *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
00887             *audiobytes1 = writebytes;
00888             if (lplpaudioptr2)
00889                 *(LPBYTE*)lplpaudioptr2 = NULL;
00890             if (audiobytes2)
00891                 *audiobytes2 = 0;
00892             TRACE("->%d.0\n",writebytes);
00893         } else {
00894             *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
00895             *audiobytes1 = device->buflen-writecursor;
00896             if (lplpaudioptr2)
00897                 *(LPBYTE*)lplpaudioptr2 = device->buffer;
00898             if (audiobytes2)
00899                 *audiobytes2 = writebytes-(device->buflen-writecursor);
00900             TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0);
00901         }
00902     }
00903     return DS_OK;
00904 }
00905 
00906 static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(
00907     LPDIRECTSOUNDBUFFER iface,DWORD newpos
00908 ) {
00909     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
00910     TRACE("(%p,%d)\n",This,newpos);
00911 
00912     /* You cannot set the position of the primary buffer */
00913     WARN("invalid call\n");
00914     return DSERR_INVALIDCALL;
00915 }
00916 
00917 static HRESULT WINAPI PrimaryBufferImpl_SetPan(
00918     LPDIRECTSOUNDBUFFER iface,LONG pan
00919 ) {
00920         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00921     DWORD ampfactors;
00922         HRESULT hres = DS_OK;
00923     TRACE("(%p,%d)\n", iface, pan);
00924 
00925     if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
00926         WARN("control unavailable\n");
00927         return DSERR_CONTROLUNAVAIL;
00928     }
00929 
00930     if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
00931         WARN("invalid parameter: pan = %d\n", pan);
00932         return DSERR_INVALIDPARAM;
00933     }
00934 
00935     /* **** */
00936     EnterCriticalSection(&(device->mixlock));
00937 
00938         if (!device->hwbuf)
00939         {
00940             waveOutGetVolume(device->hwo, &ampfactors);
00941             device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
00942             device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
00943             DSOUND_AmpFactorToVolPan(&device->volpan);
00944         }
00945         if (pan != device->volpan.lPan) {
00946             device->volpan.lPan=pan;
00947             DSOUND_RecalcVolPan(&device->volpan);
00948             if (device->hwbuf) {
00949                 hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);
00950                 if (hres != DS_OK)
00951                     WARN("IDsDriverBuffer_SetVolumePan failed\n");
00952             } else {
00953                 ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16);
00954                 waveOutSetVolume(device->hwo, ampfactors);
00955             }
00956         }
00957 
00958     LeaveCriticalSection(&(device->mixlock));
00959     /* **** */
00960 
00961     return hres;
00962 }
00963 
00964 static HRESULT WINAPI PrimaryBufferImpl_GetPan(
00965     LPDIRECTSOUNDBUFFER iface,LPLONG pan
00966 ) {
00967         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00968     DWORD ampfactors;
00969     TRACE("(%p,%p)\n", iface, pan);
00970 
00971     if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
00972         WARN("control unavailable\n");
00973         return DSERR_CONTROLUNAVAIL;
00974     }
00975 
00976     if (pan == NULL) {
00977         WARN("invalid parameter: pan == NULL\n");
00978         return DSERR_INVALIDPARAM;
00979     }
00980 
00981         if (!device->hwbuf)
00982         {
00983         waveOutGetVolume(device->hwo, &ampfactors);
00984         device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
00985         device->volpan.dwTotalRightAmpFactor=ampfactors >> 16;
00986         DSOUND_AmpFactorToVolPan(&device->volpan);
00987         }
00988     *pan = device->volpan.lPan;
00989     return DS_OK;
00990 }
00991 
00992 static HRESULT WINAPI PrimaryBufferImpl_Unlock(
00993     LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
00994 ) {
00995         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
00996     TRACE("(%p,%p,%d,%p,%d)\n", iface, p1, x1, p2, x2);
00997 
00998     if (device->priolevel != DSSCL_WRITEPRIMARY) {
00999         WARN("failed priority check!\n");
01000         return DSERR_PRIOLEVELNEEDED;
01001     }
01002 
01003     if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
01004         HRESULT hres;
01005 
01006         if ((char *)p1 - (char *)device->buffer + x1 > device->buflen)
01007             hres = DSERR_INVALIDPARAM;
01008         else
01009             hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2);
01010 
01011         if (hres != DS_OK) {
01012             WARN("IDsDriverBuffer_Unlock failed\n");
01013             return hres;
01014         }
01015     }
01016 
01017     return DS_OK;
01018 }
01019 
01020 static HRESULT WINAPI PrimaryBufferImpl_Restore(
01021     LPDIRECTSOUNDBUFFER iface
01022 ) {
01023     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
01024     FIXME("(%p):stub\n",This);
01025     return DS_OK;
01026 }
01027 
01028 static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
01029     LPDIRECTSOUNDBUFFER iface,LPDWORD freq
01030 ) {
01031         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
01032     TRACE("(%p,%p)\n", iface, freq);
01033 
01034     if (freq == NULL) {
01035         WARN("invalid parameter: freq == NULL\n");
01036         return DSERR_INVALIDPARAM;
01037     }
01038 
01039     if (!(device->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
01040         WARN("control unavailable\n");
01041         return DSERR_CONTROLUNAVAIL;
01042     }
01043 
01044     *freq = device->pwfx->nSamplesPerSec;
01045     TRACE("-> %d\n", *freq);
01046 
01047     return DS_OK;
01048 }
01049 
01050 static HRESULT WINAPI PrimaryBufferImpl_Initialize(
01051     LPDIRECTSOUNDBUFFER iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
01052 ) {
01053     PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
01054     WARN("(%p) already initialized\n", This);
01055     return DSERR_ALREADYINITIALIZED;
01056 }
01057 
01058 static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
01059     LPDIRECTSOUNDBUFFER iface,LPDSBCAPS caps
01060 ) {
01061         DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device;
01062     TRACE("(%p,%p)\n", iface, caps);
01063 
01064     if (caps == NULL) {
01065         WARN("invalid parameter: caps == NULL\n");
01066         return DSERR_INVALIDPARAM;
01067     }
01068 
01069     if (caps->dwSize < sizeof(*caps)) {
01070         WARN("invalid parameter: caps->dwSize = %d\n", caps->dwSize);
01071         return DSERR_INVALIDPARAM;
01072     }
01073 
01074     caps->dwFlags = device->dsbd.dwFlags;
01075     caps->dwBufferBytes = device->buflen;
01076 
01077     /* Windows reports these as zero */
01078     caps->dwUnlockTransferRate = 0;
01079     caps->dwPlayCpuOverhead = 0;
01080 
01081     return DS_OK;
01082 }
01083 
01084 static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
01085     LPDIRECTSOUNDBUFFER iface,REFIID riid,LPVOID *ppobj
01086 ) {
01087         PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
01088         DirectSoundDevice *device = This->device;
01089     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj);
01090 
01091     if (ppobj == NULL) {
01092         WARN("invalid parameter\n");
01093         return E_INVALIDARG;
01094     }
01095 
01096     *ppobj = NULL;  /* assume failure */
01097 
01098     if ( IsEqualGUID(riid, &IID_IUnknown) ||
01099          IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
01100         IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)This);
01101         *ppobj = This;
01102         return S_OK;
01103     }
01104 
01105     /* DirectSoundBuffer and DirectSoundBuffer8 are different and */
01106     /* a primary buffer can't have a DirectSoundBuffer8 interface */
01107     if ( IsEqualGUID( &IID_IDirectSoundBuffer8, riid ) ) {
01108         WARN("app requested DirectSoundBuffer8 on primary buffer\n");
01109         return E_NOINTERFACE;
01110     }
01111 
01112     if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
01113         ERR("app requested IDirectSoundNotify on primary buffer\n");
01114         /* FIXME: should we support this? */
01115         return E_NOINTERFACE;
01116     }
01117 
01118     if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
01119         ERR("app requested IDirectSound3DBuffer on primary buffer\n");
01120         return E_NOINTERFACE;
01121     }
01122 
01123         if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
01124         if (!device->listener)
01125             IDirectSound3DListenerImpl_Create(device, &device->listener);
01126         if (device->listener) {
01127             *ppobj = device->listener;
01128             IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
01129             return S_OK;
01130         }
01131 
01132         WARN("IID_IDirectSound3DListener failed\n");
01133         return E_NOINTERFACE;
01134     }
01135 
01136     if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
01137         FIXME("app requested IKsPropertySet on primary buffer\n");
01138         return E_NOINTERFACE;
01139     }
01140 
01141     FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
01142     return E_NOINTERFACE;
01143 }
01144 
01145 static const IDirectSoundBufferVtbl dspbvt =
01146 {
01147     PrimaryBufferImpl_QueryInterface,
01148     PrimaryBufferImpl_AddRef,
01149     PrimaryBufferImpl_Release,
01150     PrimaryBufferImpl_GetCaps,
01151     PrimaryBufferImpl_GetCurrentPosition,
01152     PrimaryBufferImpl_GetFormat,
01153     PrimaryBufferImpl_GetVolume,
01154     PrimaryBufferImpl_GetPan,
01155         PrimaryBufferImpl_GetFrequency,
01156     PrimaryBufferImpl_GetStatus,
01157     PrimaryBufferImpl_Initialize,
01158     PrimaryBufferImpl_Lock,
01159     PrimaryBufferImpl_Play,
01160     PrimaryBufferImpl_SetCurrentPosition,
01161     PrimaryBufferImpl_SetFormat,
01162     PrimaryBufferImpl_SetVolume,
01163     PrimaryBufferImpl_SetPan,
01164     PrimaryBufferImpl_SetFrequency,
01165     PrimaryBufferImpl_Stop,
01166     PrimaryBufferImpl_Unlock,
01167     PrimaryBufferImpl_Restore
01168 };
01169 
01170 HRESULT PrimaryBufferImpl_Create(
01171     DirectSoundDevice * device,
01172     PrimaryBufferImpl ** ppdsb,
01173     LPCDSBUFFERDESC dsbd)
01174 {
01175     PrimaryBufferImpl *dsb;
01176     TRACE("%p,%p,%p)\n",device,ppdsb,dsbd);
01177 
01178     if (dsbd->lpwfxFormat) {
01179         WARN("invalid parameter: dsbd->lpwfxFormat != NULL\n");
01180         *ppdsb = NULL;
01181         return DSERR_INVALIDPARAM;
01182     }
01183 
01184     dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
01185 
01186     if (dsb == NULL) {
01187         WARN("out of memory\n");
01188         *ppdsb = NULL;
01189         return DSERR_OUTOFMEMORY;
01190     }
01191 
01192     dsb->ref = 0;
01193     dsb->device = device;
01194     dsb->lpVtbl = &dspbvt;
01195 
01196     device->dsbd = *dsbd;
01197 
01198     TRACE("Created primary buffer at %p\n", dsb);
01199     TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
01200         "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
01201         device->pwfx->wFormatTag, device->pwfx->nChannels,
01202                 device->pwfx->nSamplesPerSec, device->pwfx->nAvgBytesPerSec,
01203                 device->pwfx->nBlockAlign, device->pwfx->wBitsPerSample,
01204                 device->pwfx->cbSize);
01205 
01206     *ppdsb = dsb;
01207     return S_OK;
01208 }

Generated on Fri May 25 2012 04:19:36 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.