Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendsound.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
1.7.6.1
|