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

dsound.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  * Copyright 2004 Robert Reif
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include <stdarg.h>
00024 #include <stdio.h>
00025 
00026 #define NONAMELESSSTRUCT
00027 #define NONAMELESSUNION
00028 #include "windef.h"
00029 #include "winbase.h"
00030 #include "winuser.h"
00031 #include "mmsystem.h"
00032 #include "winternl.h"
00033 #include "mmddk.h"
00034 #include "wingdi.h"
00035 #include "mmreg.h"
00036 #include "ks.h"
00037 #include "ksmedia.h"
00038 #include "wine/debug.h"
00039 #include "dsound.h"
00040 #include "dsdriver.h"
00041 #include "dsound_private.h"
00042 
00043 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
00044 
00045 /*****************************************************************************
00046  * IDirectSound COM components
00047  */
00048 struct IDirectSound_IUnknown {
00049     const IUnknownVtbl         *lpVtbl;
00050     LONG                        ref;
00051     LPDIRECTSOUND8              pds;
00052 };
00053 
00054 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
00055 
00056 struct IDirectSound_IDirectSound {
00057     const IDirectSoundVtbl     *lpVtbl;
00058     LONG                        ref;
00059     LPDIRECTSOUND8              pds;
00060 };
00061 
00062 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
00063 
00064 /*****************************************************************************
00065  * IDirectSound8 COM components
00066  */
00067 struct IDirectSound8_IUnknown {
00068     const IUnknownVtbl         *lpVtbl;
00069     LONG                        ref;
00070     LPDIRECTSOUND8              pds;
00071 };
00072 
00073 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
00074 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
00075 
00076 struct IDirectSound8_IDirectSound {
00077     const IDirectSoundVtbl     *lpVtbl;
00078     LONG                        ref;
00079     LPDIRECTSOUND8              pds;
00080 };
00081 
00082 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
00083 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
00084 
00085 struct IDirectSound8_IDirectSound8 {
00086     const IDirectSound8Vtbl    *lpVtbl;
00087     LONG                        ref;
00088     LPDIRECTSOUND8              pds;
00089 };
00090 
00091 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
00092 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
00093 
00094 /*****************************************************************************
00095  * IDirectSound implementation structure
00096  */
00097 struct IDirectSoundImpl
00098 {
00099     LONG                        ref;
00100 
00101     DirectSoundDevice          *device;
00102     LPUNKNOWN                   pUnknown;
00103     LPDIRECTSOUND               pDS;
00104     LPDIRECTSOUND8              pDS8;
00105 };
00106 
00107 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
00108 
00109 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
00110 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
00111 
00112 static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified);
00113 
00114 const char * dumpCooperativeLevel(DWORD level)
00115 {
00116     static char unknown[32];
00117 #define LE(x) case x: return #x
00118     switch (level) {
00119         LE(DSSCL_NORMAL);
00120         LE(DSSCL_PRIORITY);
00121         LE(DSSCL_EXCLUSIVE);
00122         LE(DSSCL_WRITEPRIMARY);
00123     }
00124 #undef LE
00125     sprintf(unknown, "Unknown(%08x)", (UINT)level);
00126     return unknown;
00127 }
00128 
00129 static void _dump_DSCAPS(DWORD xmask) {
00130     struct {
00131         DWORD   mask;
00132         const char    *name;
00133     } flags[] = {
00134 #define FE(x) { x, #x },
00135         FE(DSCAPS_PRIMARYMONO)
00136         FE(DSCAPS_PRIMARYSTEREO)
00137         FE(DSCAPS_PRIMARY8BIT)
00138         FE(DSCAPS_PRIMARY16BIT)
00139         FE(DSCAPS_CONTINUOUSRATE)
00140         FE(DSCAPS_EMULDRIVER)
00141         FE(DSCAPS_CERTIFIED)
00142         FE(DSCAPS_SECONDARYMONO)
00143         FE(DSCAPS_SECONDARYSTEREO)
00144         FE(DSCAPS_SECONDARY8BIT)
00145         FE(DSCAPS_SECONDARY16BIT)
00146 #undef FE
00147     };
00148     unsigned int     i;
00149 
00150     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
00151         if ((flags[i].mask & xmask) == flags[i].mask)
00152             TRACE("%s ",flags[i].name);
00153 }
00154 
00155 static void _dump_DSBCAPS(DWORD xmask) {
00156     struct {
00157         DWORD   mask;
00158         const char    *name;
00159     } flags[] = {
00160 #define FE(x) { x, #x },
00161         FE(DSBCAPS_PRIMARYBUFFER)
00162         FE(DSBCAPS_STATIC)
00163         FE(DSBCAPS_LOCHARDWARE)
00164         FE(DSBCAPS_LOCSOFTWARE)
00165         FE(DSBCAPS_CTRL3D)
00166         FE(DSBCAPS_CTRLFREQUENCY)
00167         FE(DSBCAPS_CTRLPAN)
00168         FE(DSBCAPS_CTRLVOLUME)
00169         FE(DSBCAPS_CTRLPOSITIONNOTIFY)
00170         FE(DSBCAPS_STICKYFOCUS)
00171         FE(DSBCAPS_GLOBALFOCUS)
00172         FE(DSBCAPS_GETCURRENTPOSITION2)
00173         FE(DSBCAPS_MUTE3DATMAXDISTANCE)
00174 #undef FE
00175     };
00176     unsigned int     i;
00177 
00178     for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
00179         if ((flags[i].mask & xmask) == flags[i].mask)
00180             TRACE("%s ",flags[i].name);
00181 }
00182 
00183 /*******************************************************************************
00184  *      IDirectSoundImpl_DirectSound
00185  */
00186 static HRESULT DSOUND_QueryInterface(
00187     LPDIRECTSOUND8 iface,
00188     REFIID riid,
00189     LPVOID * ppobj)
00190 {
00191     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
00192     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00193 
00194     if (ppobj == NULL) {
00195         WARN("invalid parameter\n");
00196         return E_INVALIDARG;
00197     }
00198 
00199     if (IsEqualIID(riid, &IID_IUnknown)) {
00200         if (!This->pUnknown) {
00201             IDirectSound_IUnknown_Create(iface, &This->pUnknown);
00202             if (!This->pUnknown) {
00203                 WARN("IDirectSound_IUnknown_Create() failed\n");
00204                 *ppobj = NULL;
00205                 return E_NOINTERFACE;
00206             }
00207         }
00208         IDirectSound_IUnknown_AddRef(This->pUnknown);
00209         *ppobj = This->pUnknown;
00210         return S_OK;
00211     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
00212         if (!This->pDS) {
00213             IDirectSound_IDirectSound_Create(iface, &This->pDS);
00214             if (!This->pDS) {
00215                 WARN("IDirectSound_IDirectSound_Create() failed\n");
00216                 *ppobj = NULL;
00217                 return E_NOINTERFACE;
00218             }
00219         }
00220         IDirectSound_IDirectSound_AddRef(This->pDS);
00221         *ppobj = This->pDS;
00222         return S_OK;
00223     }
00224 
00225     *ppobj = NULL;
00226     WARN("Unknown IID %s\n",debugstr_guid(riid));
00227     return E_NOINTERFACE;
00228 }
00229 
00230 static HRESULT DSOUND_QueryInterface8(
00231     LPDIRECTSOUND8 iface,
00232     REFIID riid,
00233     LPVOID * ppobj)
00234 {
00235     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
00236     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00237 
00238     if (ppobj == NULL) {
00239         WARN("invalid parameter\n");
00240         return E_INVALIDARG;
00241     }
00242 
00243     if (IsEqualIID(riid, &IID_IUnknown)) {
00244         if (!This->pUnknown) {
00245             IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
00246             if (!This->pUnknown) {
00247                 WARN("IDirectSound8_IUnknown_Create() failed\n");
00248                 *ppobj = NULL;
00249                 return E_NOINTERFACE;
00250             }
00251         }
00252         IDirectSound8_IUnknown_AddRef(This->pUnknown);
00253         *ppobj = This->pUnknown;
00254         return S_OK;
00255     } else if (IsEqualIID(riid, &IID_IDirectSound)) {
00256         if (!This->pDS) {
00257             IDirectSound8_IDirectSound_Create(iface, &This->pDS);
00258             if (!This->pDS) {
00259                 WARN("IDirectSound8_IDirectSound_Create() failed\n");
00260                 *ppobj = NULL;
00261                 return E_NOINTERFACE;
00262             }
00263         }
00264         IDirectSound8_IDirectSound_AddRef(This->pDS);
00265         *ppobj = This->pDS;
00266         return S_OK;
00267     } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
00268         if (!This->pDS8) {
00269             IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
00270             if (!This->pDS8) {
00271                 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
00272                 *ppobj = NULL;
00273                 return E_NOINTERFACE;
00274             }
00275         }
00276         IDirectSound8_IDirectSound8_AddRef(This->pDS8);
00277         *ppobj = This->pDS8;
00278         return S_OK;
00279     }
00280 
00281     *ppobj = NULL;
00282     WARN("Unknown IID %s\n",debugstr_guid(riid));
00283     return E_NOINTERFACE;
00284 }
00285 
00286 static ULONG IDirectSoundImpl_AddRef(
00287     LPDIRECTSOUND8 iface)
00288 {
00289     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
00290     ULONG ref = InterlockedIncrement(&(This->ref));
00291     TRACE("(%p) ref was %d\n", This, ref - 1);
00292     return ref;
00293 }
00294 
00295 static ULONG IDirectSoundImpl_Release(
00296     LPDIRECTSOUND8 iface)
00297 {
00298     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
00299     ULONG ref = InterlockedDecrement(&(This->ref));
00300     TRACE("(%p) ref was %d\n", This, ref + 1);
00301 
00302     if (!ref) {
00303         if (This->device)
00304             DirectSoundDevice_Release(This->device);
00305         HeapFree(GetProcessHeap(),0,This);
00306         TRACE("(%p) released\n", This);
00307     }
00308     return ref;
00309 }
00310 
00311 static HRESULT IDirectSoundImpl_Create(
00312     LPDIRECTSOUND8 * ppDS)
00313 {
00314     IDirectSoundImpl* pDS;
00315     TRACE("(%p)\n",ppDS);
00316 
00317     /* Allocate memory */
00318     pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
00319     if (pDS == NULL) {
00320         WARN("out of memory\n");
00321         *ppDS = NULL;
00322         return DSERR_OUTOFMEMORY;
00323     }
00324 
00325     pDS->ref    = 0;
00326     pDS->device = NULL;
00327 
00328     *ppDS = (LPDIRECTSOUND8)pDS;
00329 
00330     return DS_OK;
00331 }
00332 
00333 /*******************************************************************************
00334  *      IDirectSound_IUnknown
00335  */
00336 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
00337     LPUNKNOWN iface,
00338     REFIID riid,
00339     LPVOID * ppobj)
00340 {
00341     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00342     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00343     return DSOUND_QueryInterface(This->pds, riid, ppobj);
00344 }
00345 
00346 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
00347     LPUNKNOWN iface)
00348 {
00349     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00350     ULONG ref = InterlockedIncrement(&(This->ref));
00351     TRACE("(%p) ref was %d\n", This, ref - 1);
00352     return ref;
00353 }
00354 
00355 static ULONG WINAPI IDirectSound_IUnknown_Release(
00356     LPUNKNOWN iface)
00357 {
00358     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00359     ULONG ref = InterlockedDecrement(&(This->ref));
00360     TRACE("(%p) ref was %d\n", This, ref + 1);
00361     if (!ref) {
00362         ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
00363         IDirectSoundImpl_Release(This->pds);
00364         HeapFree(GetProcessHeap(), 0, This);
00365         TRACE("(%p) released\n", This);
00366     }
00367     return ref;
00368 }
00369 
00370 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
00371 {
00372     IDirectSound_IUnknown_QueryInterface,
00373     IDirectSound_IUnknown_AddRef,
00374     IDirectSound_IUnknown_Release
00375 };
00376 
00377 static HRESULT IDirectSound_IUnknown_Create(
00378     LPDIRECTSOUND8 pds,
00379     LPUNKNOWN * ppunk)
00380 {
00381     IDirectSound_IUnknown * pdsunk;
00382     TRACE("(%p,%p)\n",pds,ppunk);
00383 
00384     if (ppunk == NULL) {
00385         ERR("invalid parameter: ppunk == NULL\n");
00386         return DSERR_INVALIDPARAM;
00387     }
00388 
00389     if (pds == NULL) {
00390         ERR("invalid parameter: pds == NULL\n");
00391         *ppunk = NULL;
00392         return DSERR_INVALIDPARAM;
00393     }
00394 
00395     pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
00396     if (pdsunk == NULL) {
00397         WARN("out of memory\n");
00398         *ppunk = NULL;
00399         return DSERR_OUTOFMEMORY;
00400     }
00401 
00402     pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
00403     pdsunk->ref = 0;
00404     pdsunk->pds = pds;
00405 
00406     IDirectSoundImpl_AddRef(pds);
00407     *ppunk = (LPUNKNOWN)pdsunk;
00408 
00409     return DS_OK;
00410 }
00411 
00412 /*******************************************************************************
00413  *      IDirectSound_IDirectSound
00414  */
00415 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
00416     LPDIRECTSOUND iface,
00417     REFIID riid,
00418     LPVOID * ppobj)
00419 {
00420     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00421     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00422     return DSOUND_QueryInterface(This->pds, riid, ppobj);
00423 }
00424 
00425 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
00426     LPDIRECTSOUND iface)
00427 {
00428     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00429     ULONG ref = InterlockedIncrement(&(This->ref));
00430     TRACE("(%p) ref was %d\n", This, ref - 1);
00431     return ref;
00432 }
00433 
00434 static ULONG WINAPI IDirectSound_IDirectSound_Release(
00435     LPDIRECTSOUND iface)
00436 {
00437     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00438     ULONG ref = InterlockedDecrement(&(This->ref));
00439     TRACE("(%p) ref was %d\n", This, ref + 1);
00440     if (!ref) {
00441         ((IDirectSoundImpl*)This->pds)->pDS = NULL;
00442         IDirectSoundImpl_Release(This->pds);
00443         HeapFree(GetProcessHeap(), 0, This);
00444         TRACE("(%p) released\n", This);
00445     }
00446     return ref;
00447 }
00448 
00449 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
00450     LPDIRECTSOUND iface,
00451     LPCDSBUFFERDESC dsbd,
00452     LPLPDIRECTSOUNDBUFFER ppdsb,
00453     LPUNKNOWN lpunk)
00454 {
00455     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00456     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
00457     return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
00458 }
00459 
00460 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
00461     LPDIRECTSOUND iface,
00462     LPDSCAPS lpDSCaps)
00463 {
00464     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00465     TRACE("(%p,%p)\n",This,lpDSCaps);
00466     return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
00467 }
00468 
00469 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
00470     LPDIRECTSOUND iface,
00471     LPDIRECTSOUNDBUFFER psb,
00472     LPLPDIRECTSOUNDBUFFER ppdsb)
00473 {
00474     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00475     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
00476     return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
00477 }
00478 
00479 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
00480     LPDIRECTSOUND iface,
00481     HWND hwnd,
00482     DWORD level)
00483 {
00484     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00485     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
00486     return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
00487 }
00488 
00489 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
00490     LPDIRECTSOUND iface)
00491 {
00492     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00493     TRACE("(%p)\n", This);
00494     return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
00495 }
00496 
00497 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
00498     LPDIRECTSOUND iface,
00499     LPDWORD lpdwSpeakerConfig)
00500 {
00501     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00502     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
00503     return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
00504 }
00505 
00506 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
00507     LPDIRECTSOUND iface,
00508     DWORD config)
00509 {
00510     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00511     TRACE("(%p,0x%08x)\n",This,config);
00512     return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
00513 }
00514 
00515 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
00516     LPDIRECTSOUND iface,
00517     LPCGUID lpcGuid)
00518 {
00519     IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
00520     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
00521     return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
00522 }
00523 
00524 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
00525 {
00526     IDirectSound_IDirectSound_QueryInterface,
00527     IDirectSound_IDirectSound_AddRef,
00528     IDirectSound_IDirectSound_Release,
00529     IDirectSound_IDirectSound_CreateSoundBuffer,
00530     IDirectSound_IDirectSound_GetCaps,
00531     IDirectSound_IDirectSound_DuplicateSoundBuffer,
00532     IDirectSound_IDirectSound_SetCooperativeLevel,
00533     IDirectSound_IDirectSound_Compact,
00534     IDirectSound_IDirectSound_GetSpeakerConfig,
00535     IDirectSound_IDirectSound_SetSpeakerConfig,
00536     IDirectSound_IDirectSound_Initialize
00537 };
00538 
00539 static HRESULT IDirectSound_IDirectSound_Create(
00540     LPDIRECTSOUND8  pds,
00541     LPDIRECTSOUND * ppds)
00542 {
00543     IDirectSound_IDirectSound * pdsds;
00544     TRACE("(%p,%p)\n",pds,ppds);
00545 
00546     if (ppds == NULL) {
00547         ERR("invalid parameter: ppds == NULL\n");
00548         return DSERR_INVALIDPARAM;
00549     }
00550 
00551     if (pds == NULL) {
00552         ERR("invalid parameter: pds == NULL\n");
00553         *ppds = NULL;
00554         return DSERR_INVALIDPARAM;
00555     }
00556 
00557     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
00558     if (pdsds == NULL) {
00559         WARN("out of memory\n");
00560         *ppds = NULL;
00561         return DSERR_OUTOFMEMORY;
00562     }
00563 
00564     pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
00565     pdsds->ref = 0;
00566     pdsds->pds = pds;
00567 
00568     IDirectSoundImpl_AddRef(pds);
00569     *ppds = (LPDIRECTSOUND)pdsds;
00570 
00571     return DS_OK;
00572 }
00573 
00574 /*******************************************************************************
00575  *      IDirectSound8_IUnknown
00576  */
00577 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
00578     LPUNKNOWN iface,
00579     REFIID riid,
00580     LPVOID * ppobj)
00581 {
00582     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00583     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00584     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
00585 }
00586 
00587 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
00588     LPUNKNOWN iface)
00589 {
00590     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00591     ULONG ref = InterlockedIncrement(&(This->ref));
00592     TRACE("(%p) ref was %d\n", This, ref - 1);
00593     return ref;
00594 }
00595 
00596 static ULONG WINAPI IDirectSound8_IUnknown_Release(
00597     LPUNKNOWN iface)
00598 {
00599     IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
00600     ULONG ref = InterlockedDecrement(&(This->ref));
00601     TRACE("(%p) ref was %d\n", This, ref + 1);
00602     if (!ref) {
00603         ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
00604         IDirectSoundImpl_Release(This->pds);
00605         HeapFree(GetProcessHeap(), 0, This);
00606         TRACE("(%p) released\n", This);
00607     }
00608     return ref;
00609 }
00610 
00611 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
00612 {
00613     IDirectSound8_IUnknown_QueryInterface,
00614     IDirectSound8_IUnknown_AddRef,
00615     IDirectSound8_IUnknown_Release
00616 };
00617 
00618 static HRESULT IDirectSound8_IUnknown_Create(
00619     LPDIRECTSOUND8 pds,
00620     LPUNKNOWN * ppunk)
00621 {
00622     IDirectSound8_IUnknown * pdsunk;
00623     TRACE("(%p,%p)\n",pds,ppunk);
00624 
00625     if (ppunk == NULL) {
00626         ERR("invalid parameter: ppunk == NULL\n");
00627         return DSERR_INVALIDPARAM;
00628     }
00629 
00630     if (pds == NULL) {
00631         ERR("invalid parameter: pds == NULL\n");
00632         *ppunk = NULL;
00633         return DSERR_INVALIDPARAM;
00634     }
00635 
00636     pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
00637     if (pdsunk == NULL) {
00638         WARN("out of memory\n");
00639         *ppunk = NULL;
00640         return DSERR_OUTOFMEMORY;
00641     }
00642 
00643     pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
00644     pdsunk->ref = 0;
00645     pdsunk->pds = pds;
00646 
00647     IDirectSoundImpl_AddRef(pds);
00648     *ppunk = (LPUNKNOWN)pdsunk;
00649 
00650     return DS_OK;
00651 }
00652 
00653 /*******************************************************************************
00654  *      IDirectSound8_IDirectSound
00655  */
00656 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
00657     LPDIRECTSOUND iface,
00658     REFIID riid,
00659     LPVOID * ppobj)
00660 {
00661     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00662     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00663     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
00664 }
00665 
00666 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
00667     LPDIRECTSOUND iface)
00668 {
00669     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00670     ULONG ref = InterlockedIncrement(&(This->ref));
00671     TRACE("(%p) ref was %d\n", This, ref - 1);
00672     return ref;
00673 }
00674 
00675 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
00676     LPDIRECTSOUND iface)
00677 {
00678     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00679     ULONG ref = InterlockedDecrement(&(This->ref));
00680     TRACE("(%p) ref was %d\n", This, ref + 1);
00681     if (!ref) {
00682         ((IDirectSoundImpl*)This->pds)->pDS = NULL;
00683         IDirectSoundImpl_Release(This->pds);
00684         HeapFree(GetProcessHeap(), 0, This);
00685         TRACE("(%p) released\n", This);
00686     }
00687     return ref;
00688 }
00689 
00690 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
00691     LPDIRECTSOUND iface,
00692     LPCDSBUFFERDESC dsbd,
00693     LPLPDIRECTSOUNDBUFFER ppdsb,
00694     LPUNKNOWN lpunk)
00695 {
00696     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00697     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
00698     return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
00699 }
00700 
00701 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
00702     LPDIRECTSOUND iface,
00703     LPDSCAPS lpDSCaps)
00704 {
00705     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00706     TRACE("(%p,%p)\n",This,lpDSCaps);
00707     return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
00708 }
00709 
00710 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
00711     LPDIRECTSOUND iface,
00712     LPDIRECTSOUNDBUFFER psb,
00713     LPLPDIRECTSOUNDBUFFER ppdsb)
00714 {
00715     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00716     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
00717     return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
00718 }
00719 
00720 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
00721     LPDIRECTSOUND iface,
00722     HWND hwnd,
00723     DWORD level)
00724 {
00725     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00726     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
00727     return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
00728 }
00729 
00730 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
00731     LPDIRECTSOUND iface)
00732 {
00733     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00734     TRACE("(%p)\n", This);
00735     return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
00736 }
00737 
00738 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
00739     LPDIRECTSOUND iface,
00740     LPDWORD lpdwSpeakerConfig)
00741 {
00742     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00743     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
00744     return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
00745 }
00746 
00747 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
00748     LPDIRECTSOUND iface,
00749     DWORD config)
00750 {
00751     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00752     TRACE("(%p,0x%08x)\n",This,config);
00753     return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
00754 }
00755 
00756 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
00757     LPDIRECTSOUND iface,
00758     LPCGUID lpcGuid)
00759 {
00760     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00761     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
00762     return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
00763 }
00764 
00765 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
00766 {
00767     IDirectSound8_IDirectSound_QueryInterface,
00768     IDirectSound8_IDirectSound_AddRef,
00769     IDirectSound8_IDirectSound_Release,
00770     IDirectSound8_IDirectSound_CreateSoundBuffer,
00771     IDirectSound8_IDirectSound_GetCaps,
00772     IDirectSound8_IDirectSound_DuplicateSoundBuffer,
00773     IDirectSound8_IDirectSound_SetCooperativeLevel,
00774     IDirectSound8_IDirectSound_Compact,
00775     IDirectSound8_IDirectSound_GetSpeakerConfig,
00776     IDirectSound8_IDirectSound_SetSpeakerConfig,
00777     IDirectSound8_IDirectSound_Initialize
00778 };
00779 
00780 static HRESULT IDirectSound8_IDirectSound_Create(
00781     LPDIRECTSOUND8 pds,
00782     LPDIRECTSOUND * ppds)
00783 {
00784     IDirectSound8_IDirectSound * pdsds;
00785     TRACE("(%p,%p)\n",pds,ppds);
00786 
00787     if (ppds == NULL) {
00788         ERR("invalid parameter: ppds == NULL\n");
00789         return DSERR_INVALIDPARAM;
00790     }
00791 
00792     if (pds == NULL) {
00793         ERR("invalid parameter: pds == NULL\n");
00794         *ppds = NULL;
00795         return DSERR_INVALIDPARAM;
00796     }
00797 
00798     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
00799     if (pdsds == NULL) {
00800         WARN("out of memory\n");
00801         *ppds = NULL;
00802         return DSERR_OUTOFMEMORY;
00803     }
00804 
00805     pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
00806     pdsds->ref = 0;
00807     pdsds->pds = pds;
00808 
00809     IDirectSoundImpl_AddRef(pds);
00810     *ppds = (LPDIRECTSOUND)pdsds;
00811 
00812     return DS_OK;
00813 }
00814 
00815 /*******************************************************************************
00816  *      IDirectSound8_IDirectSound8
00817  */
00818 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
00819     LPDIRECTSOUND8 iface,
00820     REFIID riid,
00821     LPVOID * ppobj)
00822 {
00823     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00824     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00825     return DSOUND_QueryInterface8(This->pds, riid, ppobj);
00826 }
00827 
00828 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
00829     LPDIRECTSOUND8 iface)
00830 {
00831     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00832     ULONG ref = InterlockedIncrement(&(This->ref));
00833     TRACE("(%p) ref was %d\n", This, ref - 1);
00834     return ref;
00835 }
00836 
00837 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
00838     LPDIRECTSOUND8 iface)
00839 {
00840     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00841     ULONG ref = InterlockedDecrement(&(This->ref));
00842     TRACE("(%p) ref was %d\n", This, ref + 1);
00843     if (!ref) {
00844         ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
00845         IDirectSoundImpl_Release(This->pds);
00846         HeapFree(GetProcessHeap(), 0, This);
00847         TRACE("(%p) released\n", This);
00848     }
00849     return ref;
00850 }
00851 
00852 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
00853     LPDIRECTSOUND8 iface,
00854     LPCDSBUFFERDESC dsbd,
00855     LPLPDIRECTSOUNDBUFFER ppdsb,
00856     LPUNKNOWN lpunk)
00857 {
00858     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00859     TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
00860     return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
00861 }
00862 
00863 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
00864     LPDIRECTSOUND8 iface,
00865     LPDSCAPS lpDSCaps)
00866 {
00867     IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
00868     TRACE("(%p,%p)\n",This,lpDSCaps);
00869     return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
00870 }
00871 
00872 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
00873     LPDIRECTSOUND8 iface,
00874     LPDIRECTSOUNDBUFFER psb,
00875     LPLPDIRECTSOUNDBUFFER ppdsb)
00876 {
00877     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00878     TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
00879     return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
00880 }
00881 
00882 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
00883     LPDIRECTSOUND8 iface,
00884     HWND hwnd,
00885     DWORD level)
00886 {
00887     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00888     TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
00889     return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
00890 }
00891 
00892 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
00893     LPDIRECTSOUND8 iface)
00894 {
00895     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00896     TRACE("(%p)\n", This);
00897     return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
00898 }
00899 
00900 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
00901     LPDIRECTSOUND8 iface,
00902     LPDWORD lpdwSpeakerConfig)
00903 {
00904     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00905     TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
00906     return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
00907 }
00908 
00909 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
00910     LPDIRECTSOUND8 iface,
00911     DWORD config)
00912 {
00913     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00914     TRACE("(%p,0x%08x)\n",This,config);
00915     return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
00916 }
00917 
00918 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
00919     LPDIRECTSOUND8 iface,
00920     LPCGUID lpcGuid)
00921 {
00922     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00923     TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
00924     return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
00925 }
00926 
00927 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
00928     LPDIRECTSOUND8 iface,
00929     LPDWORD pdwCertified)
00930 {
00931     IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
00932     TRACE("(%p, %p)\n", This, pdwCertified);
00933     return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
00934 }
00935 
00936 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
00937 {
00938     IDirectSound8_IDirectSound8_QueryInterface,
00939     IDirectSound8_IDirectSound8_AddRef,
00940     IDirectSound8_IDirectSound8_Release,
00941     IDirectSound8_IDirectSound8_CreateSoundBuffer,
00942     IDirectSound8_IDirectSound8_GetCaps,
00943     IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
00944     IDirectSound8_IDirectSound8_SetCooperativeLevel,
00945     IDirectSound8_IDirectSound8_Compact,
00946     IDirectSound8_IDirectSound8_GetSpeakerConfig,
00947     IDirectSound8_IDirectSound8_SetSpeakerConfig,
00948     IDirectSound8_IDirectSound8_Initialize,
00949     IDirectSound8_IDirectSound8_VerifyCertification
00950 };
00951 
00952 static HRESULT IDirectSound8_IDirectSound8_Create(
00953     LPDIRECTSOUND8 pds,
00954     LPDIRECTSOUND8 * ppds)
00955 {
00956     IDirectSound8_IDirectSound8 * pdsds;
00957     TRACE("(%p,%p)\n",pds,ppds);
00958 
00959     if (ppds == NULL) {
00960         ERR("invalid parameter: ppds == NULL\n");
00961         return DSERR_INVALIDPARAM;
00962     }
00963 
00964     if (pds == NULL) {
00965         ERR("invalid parameter: pds == NULL\n");
00966         *ppds = NULL;
00967         return DSERR_INVALIDPARAM;
00968     }
00969 
00970     pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
00971     if (pdsds == NULL) {
00972         WARN("out of memory\n");
00973         *ppds = NULL;
00974         return DSERR_OUTOFMEMORY;
00975     }
00976 
00977     pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
00978     pdsds->ref = 0;
00979     pdsds->pds = pds;
00980 
00981     IDirectSoundImpl_AddRef(pds);
00982     *ppds = (LPDIRECTSOUND8)pdsds;
00983 
00984     return DS_OK;
00985 }
00986 
00987 HRESULT DSOUND_Create(
00988     REFIID riid,
00989     LPDIRECTSOUND *ppDS)
00990 {
00991     LPDIRECTSOUND8 pDS;
00992     HRESULT hr;
00993     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
00994 
00995     if (!IsEqualIID(riid, &IID_IUnknown) &&
00996         !IsEqualIID(riid, &IID_IDirectSound)) {
00997         *ppDS = 0;
00998         return E_NOINTERFACE;
00999     }
01000 
01001     /* Get dsound configuration */
01002     setup_dsound_options();
01003 
01004     hr = IDirectSoundImpl_Create(&pDS);
01005     if (hr == DS_OK) {
01006         hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
01007         if (*ppDS)
01008             IDirectSound_IDirectSound_AddRef(*ppDS);
01009         else {
01010             WARN("IDirectSound_IDirectSound_Create failed\n");
01011             IDirectSound8_Release(pDS);
01012         }
01013     } else {
01014         WARN("IDirectSoundImpl_Create failed\n");
01015         *ppDS = 0;
01016     }
01017 
01018     return hr;
01019 }
01020 
01021 /*******************************************************************************
01022  *      DirectSoundCreate (DSOUND.1)
01023  *
01024  *  Creates and initializes a DirectSound interface.
01025  *
01026  *  PARAMS
01027  *     lpcGUID   [I] Address of the GUID that identifies the sound device.
01028  *     ppDS      [O] Address of a variable to receive the interface pointer.
01029  *     pUnkOuter [I] Must be NULL.
01030  *
01031  *  RETURNS
01032  *     Success: DS_OK
01033  *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
01034  *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
01035  */
01036 HRESULT WINAPI DirectSoundCreate(
01037     LPCGUID lpcGUID,
01038     LPDIRECTSOUND *ppDS,
01039     IUnknown *pUnkOuter)
01040 {
01041     HRESULT hr;
01042     LPDIRECTSOUND pDS;
01043 
01044     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
01045 
01046     if (ppDS == NULL) {
01047         WARN("invalid parameter: ppDS == NULL\n");
01048         return DSERR_INVALIDPARAM;
01049     }
01050 
01051     if (pUnkOuter != NULL) {
01052         WARN("invalid parameter: pUnkOuter != NULL\n");
01053         *ppDS = 0;
01054         return DSERR_INVALIDPARAM;
01055     }
01056 
01057     hr = DSOUND_Create(&IID_IDirectSound, &pDS);
01058     if (hr == DS_OK) {
01059         hr = IDirectSound_Initialize(pDS, lpcGUID);
01060         if (hr != DS_OK) {
01061             if (hr != DSERR_ALREADYINITIALIZED) {
01062                 IDirectSound_Release(pDS);
01063                 pDS = 0;
01064             } else
01065                 hr = DS_OK;
01066         }
01067     }
01068 
01069     *ppDS = pDS;
01070 
01071     return hr;
01072 }
01073 
01074 HRESULT DSOUND_Create8(
01075     REFIID riid,
01076     LPDIRECTSOUND8 *ppDS)
01077 {
01078     LPDIRECTSOUND8 pDS;
01079     HRESULT hr;
01080     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
01081 
01082     if (!IsEqualIID(riid, &IID_IUnknown) &&
01083         !IsEqualIID(riid, &IID_IDirectSound) &&
01084         !IsEqualIID(riid, &IID_IDirectSound8)) {
01085         *ppDS = 0;
01086         return E_NOINTERFACE;
01087     }
01088 
01089     /* Get dsound configuration */
01090     setup_dsound_options();
01091 
01092     hr = IDirectSoundImpl_Create(&pDS);
01093     if (hr == DS_OK) {
01094         hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
01095         if (*ppDS)
01096             IDirectSound8_IDirectSound8_AddRef(*ppDS);
01097         else {
01098             WARN("IDirectSound8_IDirectSound8_Create failed\n");
01099             IDirectSound8_Release(pDS);
01100         }
01101     } else {
01102         WARN("IDirectSoundImpl_Create failed\n");
01103         *ppDS = 0;
01104     }
01105 
01106     return hr;
01107 }
01108 
01109 /*******************************************************************************
01110  *        DirectSoundCreate8 (DSOUND.11)
01111  *
01112  *  Creates and initializes a DirectSound8 interface.
01113  *
01114  *  PARAMS
01115  *     lpcGUID   [I] Address of the GUID that identifies the sound device.
01116  *     ppDS      [O] Address of a variable to receive the interface pointer.
01117  *     pUnkOuter [I] Must be NULL.
01118  *
01119  *  RETURNS
01120  *     Success: DS_OK
01121  *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
01122  *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
01123  */
01124 HRESULT WINAPI DirectSoundCreate8(
01125     LPCGUID lpcGUID,
01126     LPDIRECTSOUND8 *ppDS,
01127     IUnknown *pUnkOuter)
01128 {
01129     HRESULT hr;
01130     LPDIRECTSOUND8 pDS;
01131 
01132     TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
01133 
01134     if (ppDS == NULL) {
01135         WARN("invalid parameter: ppDS == NULL\n");
01136         return DSERR_INVALIDPARAM;
01137     }
01138 
01139     if (pUnkOuter != NULL) {
01140         WARN("invalid parameter: pUnkOuter != NULL\n");
01141         *ppDS = 0;
01142         return DSERR_INVALIDPARAM;
01143     }
01144 
01145     hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
01146     if (hr == DS_OK) {
01147         hr = IDirectSound8_Initialize(pDS, lpcGUID);
01148         if (hr != DS_OK) {
01149             if (hr != DSERR_ALREADYINITIALIZED) {
01150                 IDirectSound8_Release(pDS);
01151                 pDS = 0;
01152             } else
01153                 hr = DS_OK;
01154         }
01155     }
01156 
01157     *ppDS = pDS;
01158 
01159     return hr;
01160 }
01161 
01162 /*******************************************************************************
01163  *        DirectSoundDevice
01164  */
01165 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
01166 {
01167     DirectSoundDevice * device;
01168     TRACE("(%p)\n", ppDevice);
01169 
01170     /* Allocate memory */
01171     device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
01172     if (device == NULL) {
01173         WARN("out of memory\n");
01174         return DSERR_OUTOFMEMORY;
01175     }
01176 
01177     device->ref            = 1;
01178     device->priolevel      = DSSCL_NORMAL;
01179     device->state          = STATE_STOPPED;
01180     device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
01181 
01182     /* 3D listener initial parameters */
01183     device->ds3dl.dwSize   = sizeof(DS3DLISTENER);
01184     device->ds3dl.vPosition.x = 0.0;
01185     device->ds3dl.vPosition.y = 0.0;
01186     device->ds3dl.vPosition.z = 0.0;
01187     device->ds3dl.vVelocity.x = 0.0;
01188     device->ds3dl.vVelocity.y = 0.0;
01189     device->ds3dl.vVelocity.z = 0.0;
01190     device->ds3dl.vOrientFront.x = 0.0;
01191     device->ds3dl.vOrientFront.y = 0.0;
01192     device->ds3dl.vOrientFront.z = 1.0;
01193     device->ds3dl.vOrientTop.x = 0.0;
01194     device->ds3dl.vOrientTop.y = 1.0;
01195     device->ds3dl.vOrientTop.z = 0.0;
01196     device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
01197     device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
01198     device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
01199 
01200     device->prebuf = ds_snd_queue_max;
01201     device->guid = GUID_NULL;
01202 
01203     /* Set default wave format (may need it for waveOutOpen) */
01204     device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
01205     if (device->pwfx == NULL) {
01206         WARN("out of memory\n");
01207         HeapFree(GetProcessHeap(),0,device);
01208         return DSERR_OUTOFMEMORY;
01209     }
01210 
01211     /* We rely on the sound driver to return the actual sound format of
01212      * the device if it does not support 22050x8x2 and is given the
01213      * WAVE_DIRECTSOUND flag.
01214      */
01215     device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
01216     device->pwfx->nSamplesPerSec = ds_default_sample_rate;
01217     device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
01218     device->pwfx->nChannels = 2;
01219     device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
01220     device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
01221     device->pwfx->cbSize = 0;
01222 
01223     InitializeCriticalSection(&(device->mixlock));
01224     device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
01225 
01226     RtlInitializeResource(&(device->buffer_list_lock));
01227 
01228    *ppDevice = device;
01229 
01230     return DS_OK;
01231 }
01232 
01233 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
01234 {
01235     ULONG ref = InterlockedIncrement(&(device->ref));
01236     TRACE("(%p) ref was %d\n", device, ref - 1);
01237     return ref;
01238 }
01239 
01240 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
01241 {
01242     HRESULT hr;
01243     ULONG ref = InterlockedDecrement(&(device->ref));
01244     TRACE("(%p) ref was %u\n", device, ref + 1);
01245     if (!ref) {
01246         int i;
01247         timeKillEvent(device->timerID);
01248         timeEndPeriod(DS_TIME_RES);
01249 
01250         /* The kill event should have allowed the timer process to expire
01251          * but try to grab the lock just in case. Can't hold lock because
01252          * IDirectSoundBufferImpl_Destroy also grabs the lock */
01253         RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
01254         RtlReleaseResource(&(device->buffer_list_lock));
01255 
01256         /* It is allowed to release this object even when buffers are playing */
01257         if (device->buffers) {
01258             WARN("%d secondary buffers not released\n", device->nrofbuffers);
01259             for( i=0;i<device->nrofbuffers;i++)
01260                 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
01261         }
01262 
01263         if (device->primary) {
01264             WARN("primary buffer not released\n");
01265             IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
01266         }
01267 
01268         hr = DSOUND_PrimaryDestroy(device);
01269         if (hr != DS_OK)
01270             WARN("DSOUND_PrimaryDestroy failed\n");
01271 
01272         if (device->driver)
01273             IDsDriver_Close(device->driver);
01274 
01275         if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
01276             waveOutClose(device->hwo);
01277 
01278         if (device->driver)
01279             IDsDriver_Release(device->driver);
01280 
01281         DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
01282 
01283         HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
01284         HeapFree(GetProcessHeap(), 0, device->mix_buffer);
01285         if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
01286             HeapFree(GetProcessHeap(), 0, device->buffer);
01287         RtlDeleteResource(&device->buffer_list_lock);
01288         device->mixlock.DebugInfo->Spare[0] = 0;
01289         DeleteCriticalSection(&device->mixlock);
01290         HeapFree(GetProcessHeap(),0,device);
01291         TRACE("(%p) released\n", device);
01292     }
01293     return ref;
01294 }
01295 
01296 HRESULT DirectSoundDevice_GetCaps(
01297     DirectSoundDevice * device,
01298     LPDSCAPS lpDSCaps)
01299 {
01300     TRACE("(%p,%p)\n",device,lpDSCaps);
01301 
01302     if (device == NULL) {
01303         WARN("not initialized\n");
01304         return DSERR_UNINITIALIZED;
01305     }
01306 
01307     if (lpDSCaps == NULL) {
01308         WARN("invalid parameter: lpDSCaps = NULL\n");
01309         return DSERR_INVALIDPARAM;
01310     }
01311 
01312     /* check if there is enough room */
01313     if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
01314         WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
01315         return DSERR_INVALIDPARAM;
01316     }
01317 
01318     lpDSCaps->dwFlags                           = device->drvcaps.dwFlags;
01319     if (TRACE_ON(dsound)) {
01320         TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
01321         _dump_DSCAPS(lpDSCaps->dwFlags);
01322         TRACE(")\n");
01323     }
01324     lpDSCaps->dwMinSecondarySampleRate          = device->drvcaps.dwMinSecondarySampleRate;
01325     lpDSCaps->dwMaxSecondarySampleRate          = device->drvcaps.dwMaxSecondarySampleRate;
01326     lpDSCaps->dwPrimaryBuffers                  = device->drvcaps.dwPrimaryBuffers;
01327     lpDSCaps->dwMaxHwMixingAllBuffers           = device->drvcaps.dwMaxHwMixingAllBuffers;
01328     lpDSCaps->dwMaxHwMixingStaticBuffers        = device->drvcaps.dwMaxHwMixingStaticBuffers;
01329     lpDSCaps->dwMaxHwMixingStreamingBuffers     = device->drvcaps.dwMaxHwMixingStreamingBuffers;
01330     lpDSCaps->dwFreeHwMixingAllBuffers          = device->drvcaps.dwFreeHwMixingAllBuffers;
01331     lpDSCaps->dwFreeHwMixingStaticBuffers       = device->drvcaps.dwFreeHwMixingStaticBuffers;
01332     lpDSCaps->dwFreeHwMixingStreamingBuffers    = device->drvcaps.dwFreeHwMixingStreamingBuffers;
01333     lpDSCaps->dwMaxHw3DAllBuffers               = device->drvcaps.dwMaxHw3DAllBuffers;
01334     lpDSCaps->dwMaxHw3DStaticBuffers            = device->drvcaps.dwMaxHw3DStaticBuffers;
01335     lpDSCaps->dwMaxHw3DStreamingBuffers         = device->drvcaps.dwMaxHw3DStreamingBuffers;
01336     lpDSCaps->dwFreeHw3DAllBuffers              = device->drvcaps.dwFreeHw3DAllBuffers;
01337     lpDSCaps->dwFreeHw3DStaticBuffers           = device->drvcaps.dwFreeHw3DStaticBuffers;
01338     lpDSCaps->dwFreeHw3DStreamingBuffers        = device->drvcaps.dwFreeHw3DStreamingBuffers;
01339     lpDSCaps->dwTotalHwMemBytes                 = device->drvcaps.dwTotalHwMemBytes;
01340     lpDSCaps->dwFreeHwMemBytes                  = device->drvcaps.dwFreeHwMemBytes;
01341     lpDSCaps->dwMaxContigFreeHwMemBytes         = device->drvcaps.dwMaxContigFreeHwMemBytes;
01342 
01343     /* driver doesn't have these */
01344     lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
01345     lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
01346 
01347     return DS_OK;
01348 }
01349 
01350 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
01351 {
01352     HRESULT hr = DS_OK;
01353     unsigned wod, wodn;
01354     BOOLEAN found = FALSE;
01355     GUID devGUID;
01356     DirectSoundDevice * device = *ppDevice;
01357     TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
01358 
01359     if (*ppDevice != NULL) {
01360         WARN("already initialized\n");
01361         return DSERR_ALREADYINITIALIZED;
01362     }
01363 
01364     /* Default device? */
01365     if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
01366         lpcGUID = &DSDEVID_DefaultPlayback;
01367 
01368     if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
01369         WARN("invalid parameter: lpcGUID\n");
01370         return DSERR_INVALIDPARAM;
01371     }
01372 
01373     /* Enumerate WINMM audio devices and find the one we want */
01374     wodn = waveOutGetNumDevs();
01375     if (!wodn) {
01376         WARN("no driver\n");
01377         return DSERR_NODRIVER;
01378     }
01379 
01380     for (wod=0; wod<wodn; wod++) {
01381         if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
01382             found = TRUE;
01383             break;
01384         }
01385     }
01386 
01387     if (found == FALSE) {
01388         WARN("No device found matching given ID!\n");
01389         return DSERR_NODRIVER;
01390     }
01391 
01392     if (DSOUND_renderer[wod]) {
01393         if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
01394             device = DSOUND_renderer[wod];
01395             DirectSoundDevice_AddRef(device);
01396             *ppDevice = device;
01397             return DS_OK;
01398         } else {
01399             ERR("device GUID doesn't match\n");
01400             hr = DSERR_GENERIC;
01401             return hr;
01402         }
01403     } else {
01404         hr = DirectSoundDevice_Create(&device);
01405         if (hr != DS_OK) {
01406             WARN("DirectSoundDevice_Create failed\n");
01407             return hr;
01408         }
01409     }
01410 
01411     *ppDevice = device;
01412     device->guid = devGUID;
01413     device->driver = NULL;
01414 
01415     device->drvdesc.dnDevNode = wod;
01416     hr = DSOUND_ReopenDevice(device, FALSE);
01417     if (FAILED(hr))
01418     {
01419         WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
01420         return hr;
01421     }
01422 
01423     if (device->driver) {
01424         /* the driver is now open, so it's now allowed to call GetCaps */
01425         hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
01426         if (hr != DS_OK) {
01427             WARN("IDsDriver_GetCaps failed\n");
01428             return hr;
01429         }
01430     } else {
01431         WAVEOUTCAPSA woc;
01432         hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
01433         if (hr != DS_OK) {
01434             WARN("waveOutGetDevCaps failed\n");
01435             return hr;
01436         }
01437         ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
01438         if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
01439             (woc.dwFormats & WAVE_FORMAT_2M08) ||
01440             (woc.dwFormats & WAVE_FORMAT_4M08) ||
01441             (woc.dwFormats & WAVE_FORMAT_48M08) ||
01442             (woc.dwFormats & WAVE_FORMAT_96M08)) {
01443             device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
01444             device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
01445         }
01446         if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
01447             (woc.dwFormats & WAVE_FORMAT_2M16) ||
01448             (woc.dwFormats & WAVE_FORMAT_4M16) ||
01449             (woc.dwFormats & WAVE_FORMAT_48M16) ||
01450             (woc.dwFormats & WAVE_FORMAT_96M16)) {
01451             device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
01452             device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
01453         }
01454         if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
01455             (woc.dwFormats & WAVE_FORMAT_2S08) ||
01456             (woc.dwFormats & WAVE_FORMAT_4S08) ||
01457             (woc.dwFormats & WAVE_FORMAT_48S08) ||
01458             (woc.dwFormats & WAVE_FORMAT_96S08)) {
01459             device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
01460             device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
01461         }
01462         if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
01463             (woc.dwFormats & WAVE_FORMAT_2S16) ||
01464             (woc.dwFormats & WAVE_FORMAT_4S16) ||
01465             (woc.dwFormats & WAVE_FORMAT_48S16) ||
01466             (woc.dwFormats & WAVE_FORMAT_96S16)) {
01467             device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
01468             device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
01469         }
01470         if (ds_emuldriver)
01471             device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
01472         device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
01473         device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
01474         ZeroMemory(&device->volpan, sizeof(device->volpan));
01475     }
01476 
01477     hr = DSOUND_PrimaryCreate(device);
01478     if (hr == DS_OK) {
01479         UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
01480         TIMECAPS time;
01481 
01482         DSOUND_renderer[device->drvdesc.dnDevNode] = device;
01483         timeGetDevCaps(&time, sizeof(TIMECAPS));
01484         TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
01485         if (triggertime < time.wPeriodMin)
01486             triggertime = time.wPeriodMin;
01487         if (res < time.wPeriodMin)
01488             res = time.wPeriodMin;
01489         if (timeBeginPeriod(res) == TIMERR_NOCANDO)
01490             WARN("Could not set minimum resolution, don't expect sound\n");
01491         id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
01492         if (!id)
01493         {
01494             WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
01495             id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC);
01496             if (!id) ERR("Could not create timer, sound playback will not occur\n");
01497         }
01498         DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id;
01499     } else {
01500         WARN("DSOUND_PrimaryCreate failed\n");
01501     }
01502 
01503     return hr;
01504 }
01505 
01506 HRESULT DirectSoundDevice_CreateSoundBuffer(
01507     DirectSoundDevice * device,
01508     LPCDSBUFFERDESC dsbd,
01509     LPLPDIRECTSOUNDBUFFER ppdsb,
01510     LPUNKNOWN lpunk,
01511     BOOL from8)
01512 {
01513     HRESULT hres = DS_OK;
01514     TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
01515 
01516     if (device == NULL) {
01517         WARN("not initialized\n");
01518         return DSERR_UNINITIALIZED;
01519     }
01520 
01521     if (dsbd == NULL) {
01522         WARN("invalid parameter: dsbd == NULL\n");
01523         return DSERR_INVALIDPARAM;
01524     }
01525 
01526     if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
01527         dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
01528         WARN("invalid parameter: dsbd\n");
01529         return DSERR_INVALIDPARAM;
01530     }
01531 
01532     if (ppdsb == NULL) {
01533         WARN("invalid parameter: ppdsb == NULL\n");
01534         return DSERR_INVALIDPARAM;
01535     }
01536     *ppdsb = NULL;
01537 
01538     if (TRACE_ON(dsound)) {
01539         TRACE("(structsize=%d)\n",dsbd->dwSize);
01540         TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
01541         _dump_DSBCAPS(dsbd->dwFlags);
01542         TRACE(")\n");
01543         TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
01544         TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
01545     }
01546 
01547     if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
01548         if (dsbd->lpwfxFormat != NULL) {
01549             WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
01550                  "primary buffer\n");
01551             return DSERR_INVALIDPARAM;
01552         }
01553 
01554         if (device->primary) {
01555             WARN("Primary Buffer already created\n");
01556             IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
01557             *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
01558         } else {
01559            device->dsbd = *dsbd;
01560            device->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
01561            if (device->hwbuf)
01562                device->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE;
01563            else device->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
01564            hres = PrimaryBufferImpl_Create(device, &(device->primary), &(device->dsbd));
01565            if (device->primary) {
01566                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
01567                *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
01568            } else
01569                WARN("PrimaryBufferImpl_Create failed\n");
01570         }
01571     } else {
01572         IDirectSoundBufferImpl * dsb;
01573         WAVEFORMATEXTENSIBLE *pwfxe;
01574 
01575         if (dsbd->lpwfxFormat == NULL) {
01576             WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
01577                  "secondary buffer\n");
01578             return DSERR_INVALIDPARAM;
01579         }
01580         pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
01581 
01582         if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
01583         {
01584             WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
01585             return DSERR_CONTROLUNAVAIL;
01586         }
01587         if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
01588         {
01589             if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
01590             {
01591                 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
01592                 return DSERR_INVALIDPARAM;
01593             }
01594 
01595             if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
01596             {
01597                 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
01598                 return DSERR_CONTROLUNAVAIL;
01599             }
01600 
01601             if (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
01602             {
01603                 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
01604                     FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
01605                 return DSERR_INVALIDPARAM;
01606             }
01607             if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
01608             {
01609                 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
01610                 return DSERR_INVALIDPARAM;
01611             }
01612             if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
01613             {
01614                 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
01615                 return DSERR_CONTROLUNAVAIL;
01616             }
01617         }
01618 
01619         TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
01620               "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
01621               dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
01622               dsbd->lpwfxFormat->nSamplesPerSec,
01623               dsbd->lpwfxFormat->nAvgBytesPerSec,
01624               dsbd->lpwfxFormat->nBlockAlign,
01625               dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
01626 
01627         if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
01628             WARN("invalid parameter: 3D buffer format must be mono\n");
01629             return DSERR_INVALIDPARAM;
01630         }
01631 
01632         hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
01633         if (dsb) {
01634             hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
01635             if (*ppdsb) {
01636                 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
01637                 IDirectSoundBuffer_AddRef(*ppdsb);
01638             } else
01639                 WARN("SecondaryBufferImpl_Create failed\n");
01640         } else
01641            WARN("IDirectSoundBufferImpl_Create failed\n");
01642    }
01643 
01644    return hres;
01645 }
01646 
01647 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
01648     DirectSoundDevice * device,
01649     LPDIRECTSOUNDBUFFER psb,
01650     LPLPDIRECTSOUNDBUFFER ppdsb)
01651 {
01652     HRESULT hres = DS_OK;
01653     IDirectSoundBufferImpl* dsb;
01654     TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
01655 
01656     if (device == NULL) {
01657         WARN("not initialized\n");
01658         return DSERR_UNINITIALIZED;
01659     }
01660 
01661     if (psb == NULL) {
01662         WARN("invalid parameter: psb == NULL\n");
01663         return DSERR_INVALIDPARAM;
01664     }
01665 
01666     if (ppdsb == NULL) {
01667         WARN("invalid parameter: ppdsb == NULL\n");
01668         return DSERR_INVALIDPARAM;
01669     }
01670 
01671     /* make sure we have a secondary buffer */
01672     if ((PrimaryBufferImpl *)psb == device->primary) {
01673         WARN("trying to duplicate primary buffer\n");
01674         *ppdsb = NULL;
01675         return DSERR_INVALIDCALL;
01676     }
01677 
01678     /* duplicate the actual buffer implementation */
01679     hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
01680                                            ((SecondaryBufferImpl *)psb)->dsb);
01681 
01682     if (hres == DS_OK) {
01683         /* create a new secondary buffer using the new implementation */
01684         hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
01685         if (*ppdsb) {
01686             dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
01687             IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
01688         } else {
01689             WARN("SecondaryBufferImpl_Create failed\n");
01690             IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
01691             IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
01692         }
01693     }
01694 
01695     return hres;
01696 }
01697 
01698 HRESULT DirectSoundDevice_SetCooperativeLevel(
01699     DirectSoundDevice * device,
01700     HWND hwnd,
01701     DWORD level)
01702 {
01703     TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
01704 
01705     if (device == NULL) {
01706         WARN("not initialized\n");
01707         return DSERR_UNINITIALIZED;
01708     }
01709 
01710     if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
01711         WARN("level=%s not fully supported\n",
01712              level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
01713     }
01714 
01715     device->priolevel = level;
01716     return DS_OK;
01717 }
01718 
01719 HRESULT DirectSoundDevice_Compact(
01720     DirectSoundDevice * device)
01721 {
01722     TRACE("(%p)\n", device);
01723 
01724     if (device == NULL) {
01725         WARN("not initialized\n");
01726         return DSERR_UNINITIALIZED;
01727     }
01728 
01729     if (device->priolevel < DSSCL_PRIORITY) {
01730         WARN("incorrect priority level\n");
01731         return DSERR_PRIOLEVELNEEDED;
01732     }
01733 
01734     return DS_OK;
01735 }
01736 
01737 HRESULT DirectSoundDevice_GetSpeakerConfig(
01738     DirectSoundDevice * device,
01739     LPDWORD lpdwSpeakerConfig)
01740 {
01741     TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
01742 
01743     if (device == NULL) {
01744         WARN("not initialized\n");
01745         return DSERR_UNINITIALIZED;
01746     }
01747 
01748     if (lpdwSpeakerConfig == NULL) {
01749         WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
01750         return DSERR_INVALIDPARAM;
01751     }
01752 
01753     WARN("not fully functional\n");
01754     *lpdwSpeakerConfig = device->speaker_config;
01755     return DS_OK;
01756 }
01757 
01758 HRESULT DirectSoundDevice_SetSpeakerConfig(
01759     DirectSoundDevice * device,
01760     DWORD config)
01761 {
01762     TRACE("(%p,0x%08x)\n",device,config);
01763 
01764     if (device == NULL) {
01765         WARN("not initialized\n");
01766         return DSERR_UNINITIALIZED;
01767     }
01768 
01769     device->speaker_config = config;
01770     WARN("not fully functional\n");
01771     return DS_OK;
01772 }
01773 
01774 static HRESULT DirectSoundDevice_VerifyCertification(
01775     DirectSoundDevice * device,
01776     LPDWORD pdwCertified)
01777 {
01778     TRACE("(%p, %p)\n",device,pdwCertified);
01779 
01780     if (device == NULL) {
01781         WARN("not initialized\n");
01782         return DSERR_UNINITIALIZED;
01783     }
01784 
01785     if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
01786         *pdwCertified = DS_CERTIFIED;
01787     else
01788         *pdwCertified = DS_UNCERTIFIED;
01789 
01790     return DS_OK;
01791 }
01792 
01793 /*
01794  * Add secondary buffer to buffer list.
01795  * Gets exclusive access to buffer for writing.
01796  */
01797 HRESULT DirectSoundDevice_AddBuffer(
01798     DirectSoundDevice * device,
01799     IDirectSoundBufferImpl * pDSB)
01800 {
01801     IDirectSoundBufferImpl **newbuffers;
01802     HRESULT hr = DS_OK;
01803 
01804     TRACE("(%p, %p)\n", device, pDSB);
01805 
01806     RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
01807 
01808     if (device->buffers)
01809         newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
01810     else
01811         newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
01812 
01813     if (newbuffers) {
01814         device->buffers = newbuffers;
01815         device->buffers[device->nrofbuffers] = pDSB;
01816         device->nrofbuffers++;
01817         TRACE("buffer count is now %d\n", device->nrofbuffers);
01818     } else {
01819         ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
01820         hr = DSERR_OUTOFMEMORY;
01821     }
01822 
01823     RtlReleaseResource(&(device->buffer_list_lock));
01824 
01825     return hr;
01826 }
01827 
01828 /*
01829  * Remove secondary buffer from buffer list.
01830  * Gets exclusive access to buffer for writing.
01831  */
01832 HRESULT DirectSoundDevice_RemoveBuffer(
01833     DirectSoundDevice * device,
01834     IDirectSoundBufferImpl * pDSB)
01835 {
01836     int i;
01837     HRESULT hr = DS_OK;
01838 
01839     TRACE("(%p, %p)\n", device, pDSB);
01840 
01841     RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
01842 
01843     for (i = 0; i < device->nrofbuffers; i++)
01844         if (device->buffers[i] == pDSB)
01845             break;
01846 
01847     if (i < device->nrofbuffers) {
01848         /* Put the last buffer of the list in the (now empty) position */
01849         device->buffers[i] = device->buffers[device->nrofbuffers - 1];
01850         device->nrofbuffers--;
01851         device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
01852         TRACE("buffer count is now %d\n", device->nrofbuffers);
01853     }
01854 
01855     if (device->nrofbuffers == 0) {
01856         HeapFree(GetProcessHeap(),0,device->buffers);
01857         device->buffers = NULL;
01858     }
01859 
01860     RtlReleaseResource(&(device->buffer_list_lock));
01861 
01862     return hr;
01863 }

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