1 /* DirectSoundFullDuplex 2 * 3 * Copyright 1998 Marcus Meissner 4 * Copyright 1998 Rob Riggs 5 * Copyright 2000-2001 TransGaming Technologies, Inc. 6 * Copyright 2005 Robert Reif 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "dsound_private.h" 24 25 /***************************************************************************** 26 * IDirectSoundFullDuplex implementation structure 27 */ 28 typedef struct IDirectSoundFullDuplexImpl 29 { 30 /* IUnknown fields */ 31 const IDirectSoundFullDuplexVtbl *lpVtbl; 32 LONG ref; 33 34 /* IDirectSoundFullDuplexImpl fields */ 35 IDirectSound8 *renderer_device; 36 IDirectSoundCapture *capture_device; 37 38 LPUNKNOWN pUnknown; 39 LPDIRECTSOUND8 pDS8; 40 LPDIRECTSOUNDCAPTURE pDSC; 41 } IDirectSoundFullDuplexImpl; 42 43 typedef struct IDirectSoundFullDuplex_IUnknown { 44 const IUnknownVtbl *lpVtbl; 45 LONG ref; 46 IDirectSoundFullDuplexImpl *pdsfd; 47 } IDirectSoundFullDuplex_IUnknown; 48 49 typedef struct IDirectSoundFullDuplex_IDirectSound8 { 50 const IDirectSound8Vtbl *lpVtbl; 51 LONG ref; 52 IDirectSoundFullDuplexImpl *pdsfd; 53 } IDirectSoundFullDuplex_IDirectSound8; 54 55 typedef struct IDirectSoundFullDuplex_IDirectSoundCapture { 56 const IDirectSoundCaptureVtbl *lpVtbl; 57 LONG ref; 58 IDirectSoundFullDuplexImpl *pdsfd; 59 } IDirectSoundFullDuplex_IDirectSoundCapture; 60 61 /******************************************************************************* 62 * IUnknown 63 */ 64 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface( 65 LPUNKNOWN iface, 66 REFIID riid, 67 LPVOID * ppobj) 68 { 69 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; 70 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 71 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); 72 } 73 74 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef( 75 LPUNKNOWN iface) 76 { 77 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; 78 ULONG ref = InterlockedIncrement(&(This->ref)); 79 TRACE("(%p) ref was %d\n", This, ref - 1); 80 return ref; 81 } 82 83 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release( 84 LPUNKNOWN iface) 85 { 86 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; 87 ULONG ref = InterlockedDecrement(&(This->ref)); 88 TRACE("(%p) ref was %d\n", This, ref + 1); 89 if (!ref) { 90 This->pdsfd->pUnknown = NULL; 91 HeapFree(GetProcessHeap(), 0, This); 92 TRACE("(%p) released\n", This); 93 } 94 return ref; 95 } 96 97 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl = 98 { 99 IDirectSoundFullDuplex_IUnknown_QueryInterface, 100 IDirectSoundFullDuplex_IUnknown_AddRef, 101 IDirectSoundFullDuplex_IUnknown_Release 102 }; 103 104 static HRESULT IDirectSoundFullDuplex_IUnknown_Create( 105 LPDIRECTSOUNDFULLDUPLEX pdsfd, 106 LPUNKNOWN * ppunk) 107 { 108 IDirectSoundFullDuplex_IUnknown * pdsfdunk; 109 TRACE("(%p,%p)\n",pdsfd,ppunk); 110 111 if (pdsfd == NULL) { 112 ERR("invalid parameter: pdsfd == NULL\n"); 113 return DSERR_INVALIDPARAM; 114 } 115 116 if (ppunk == NULL) { 117 ERR("invalid parameter: ppunk == NULL\n"); 118 return DSERR_INVALIDPARAM; 119 } 120 121 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk)); 122 if (pdsfdunk == NULL) { 123 WARN("out of memory\n"); 124 *ppunk = NULL; 125 return DSERR_OUTOFMEMORY; 126 } 127 128 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl; 129 pdsfdunk->ref = 0; 130 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; 131 132 *ppunk = (LPUNKNOWN)pdsfdunk; 133 134 return DS_OK; 135 } 136 137 /******************************************************************************* 138 * IDirectSoundFullDuplex_IDirectSound8 139 */ 140 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface( 141 LPDIRECTSOUND8 iface, 142 REFIID riid, 143 LPVOID * ppobj) 144 { 145 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 146 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 147 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); 148 } 149 150 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef( 151 LPDIRECTSOUND8 iface) 152 { 153 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 154 ULONG ref = InterlockedIncrement(&(This->ref)); 155 TRACE("(%p) ref was %d\n", This, ref - 1); 156 return ref; 157 } 158 159 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release( 160 LPDIRECTSOUND8 iface) 161 { 162 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 163 ULONG ref = InterlockedDecrement(&(This->ref)); 164 TRACE("(%p) ref was %d\n", This, ref + 1); 165 if (!ref) { 166 This->pdsfd->pDS8 = NULL; 167 HeapFree(GetProcessHeap(), 0, This); 168 TRACE("(%p) released\n", This); 169 } 170 return ref; 171 } 172 173 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer( 174 LPDIRECTSOUND8 iface, 175 LPCDSBUFFERDESC dsbd, 176 LPLPDIRECTSOUNDBUFFER ppdsb, 177 LPUNKNOWN lpunk) 178 { 179 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 180 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); 181 return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk); 182 } 183 184 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps( 185 LPDIRECTSOUND8 iface, 186 LPDSCAPS lpDSCaps) 187 { 188 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 189 TRACE("(%p,%p)\n",This,lpDSCaps); 190 return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps); 191 } 192 193 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer( 194 LPDIRECTSOUND8 iface, 195 LPDIRECTSOUNDBUFFER psb, 196 LPLPDIRECTSOUNDBUFFER ppdsb) 197 { 198 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 199 TRACE("(%p,%p,%p)\n",This,psb,ppdsb); 200 return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb); 201 } 202 203 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel( 204 LPDIRECTSOUND8 iface, 205 HWND hwnd, 206 DWORD level) 207 { 208 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 209 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); 210 return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level); 211 } 212 213 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact( 214 LPDIRECTSOUND8 iface) 215 { 216 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 217 TRACE("(%p)\n", This); 218 return IDirectSound8_Compact(This->pdsfd->renderer_device); 219 } 220 221 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig( 222 LPDIRECTSOUND8 iface, 223 LPDWORD lpdwSpeakerConfig) 224 { 225 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 226 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); 227 return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig); 228 } 229 230 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig( 231 LPDIRECTSOUND8 iface, 232 DWORD config) 233 { 234 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 235 TRACE("(%p,0x%08x)\n",This,config); 236 return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config); 237 } 238 239 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize( 240 LPDIRECTSOUND8 iface, 241 LPCGUID lpcGuid) 242 { 243 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 244 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); 245 return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid); 246 } 247 248 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification( 249 LPDIRECTSOUND8 iface, 250 DWORD *cert) 251 { 252 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; 253 TRACE("(%p, %p)\n", This, cert); 254 return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert); 255 } 256 257 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl = 258 { 259 IDirectSoundFullDuplex_IDirectSound8_QueryInterface, 260 IDirectSoundFullDuplex_IDirectSound8_AddRef, 261 IDirectSoundFullDuplex_IDirectSound8_Release, 262 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer, 263 IDirectSoundFullDuplex_IDirectSound8_GetCaps, 264 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer, 265 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel, 266 IDirectSoundFullDuplex_IDirectSound8_Compact, 267 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig, 268 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig, 269 IDirectSoundFullDuplex_IDirectSound8_Initialize, 270 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification 271 }; 272 273 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create( 274 LPDIRECTSOUNDFULLDUPLEX pdsfd, 275 LPDIRECTSOUND8 * ppds8) 276 { 277 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8; 278 TRACE("(%p,%p)\n",pdsfd,ppds8); 279 280 if (pdsfd == NULL) { 281 ERR("invalid parameter: pdsfd == NULL\n"); 282 return DSERR_INVALIDPARAM; 283 } 284 285 if (ppds8 == NULL) { 286 ERR("invalid parameter: ppds8 == NULL\n"); 287 return DSERR_INVALIDPARAM; 288 } 289 290 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) { 291 WARN("not initialized\n"); 292 *ppds8 = NULL; 293 return DSERR_UNINITIALIZED; 294 } 295 296 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8)); 297 if (pdsfdds8 == NULL) { 298 WARN("out of memory\n"); 299 *ppds8 = NULL; 300 return DSERR_OUTOFMEMORY; 301 } 302 303 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl; 304 pdsfdds8->ref = 0; 305 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; 306 307 *ppds8 = (LPDIRECTSOUND8)pdsfdds8; 308 309 return DS_OK; 310 } 311 312 /******************************************************************************* 313 * IDirectSoundFullDuplex_IDirectSoundCapture 314 */ 315 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface( 316 LPDIRECTSOUNDCAPTURE iface, 317 REFIID riid, 318 LPVOID * ppobj) 319 { 320 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 321 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 322 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); 323 } 324 325 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef( 326 LPDIRECTSOUNDCAPTURE iface) 327 { 328 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 329 ULONG ref = InterlockedIncrement(&(This->ref)); 330 TRACE("(%p) ref was %d\n", This, ref - 1); 331 return ref; 332 } 333 334 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release( 335 LPDIRECTSOUNDCAPTURE iface) 336 { 337 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 338 ULONG ref = InterlockedDecrement(&(This->ref)); 339 TRACE("(%p) ref was %d\n", This, ref + 1); 340 if (!ref) { 341 This->pdsfd->pDSC = NULL; 342 HeapFree(GetProcessHeap(), 0, This); 343 TRACE("(%p) released\n", This); 344 } 345 return ref; 346 } 347 348 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer( 349 LPDIRECTSOUNDCAPTURE iface, 350 LPCDSCBUFFERDESC lpcDSCBufferDesc, 351 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, 352 LPUNKNOWN pUnk) 353 { 354 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 355 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk); 356 return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk); 357 } 358 359 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps( 360 LPDIRECTSOUNDCAPTURE iface, 361 LPDSCCAPS lpDSCCaps) 362 { 363 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 364 TRACE("(%p,%p)\n",This,lpDSCCaps); 365 return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps); 366 } 367 368 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize( 369 LPDIRECTSOUNDCAPTURE iface, 370 LPCGUID lpcGUID) 371 { 372 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; 373 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID)); 374 return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID); 375 } 376 377 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl = 378 { 379 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface, 380 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef, 381 IDirectSoundFullDuplex_IDirectSoundCapture_Release, 382 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer, 383 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps, 384 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize 385 }; 386 387 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create( 388 LPDIRECTSOUNDFULLDUPLEX pdsfd, 389 LPDIRECTSOUNDCAPTURE8 * ppdsc8) 390 { 391 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc; 392 TRACE("(%p,%p)\n",pdsfd,ppdsc8); 393 394 if (pdsfd == NULL) { 395 ERR("invalid parameter: pdsfd == NULL\n"); 396 return DSERR_INVALIDPARAM; 397 } 398 399 if (ppdsc8 == NULL) { 400 ERR("invalid parameter: ppdsc8 == NULL\n"); 401 return DSERR_INVALIDPARAM; 402 } 403 404 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) { 405 WARN("not initialized\n"); 406 *ppdsc8 = NULL; 407 return DSERR_UNINITIALIZED; 408 } 409 410 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc)); 411 if (pdsfddsc == NULL) { 412 WARN("out of memory\n"); 413 *ppdsc8 = NULL; 414 return DSERR_OUTOFMEMORY; 415 } 416 417 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl; 418 pdsfddsc->ref = 0; 419 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; 420 421 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc; 422 423 return DS_OK; 424 } 425 426 /*************************************************************************** 427 * IDirectSoundFullDuplexImpl 428 */ 429 static ULONG WINAPI 430 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface ) 431 { 432 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; 433 ULONG ref = InterlockedIncrement(&(This->ref)); 434 TRACE("(%p) ref was %d\n", This, ref - 1); 435 return ref; 436 } 437 438 static HRESULT WINAPI 439 IDirectSoundFullDuplexImpl_QueryInterface( 440 LPDIRECTSOUNDFULLDUPLEX iface, 441 REFIID riid, 442 LPVOID* ppobj ) 443 { 444 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; 445 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj ); 446 447 if (ppobj == NULL) { 448 WARN("invalid parameter\n"); 449 return E_INVALIDARG; 450 } 451 452 *ppobj = NULL; 453 454 if (IsEqualIID(riid, &IID_IUnknown)) { 455 if (!This->pUnknown) { 456 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown); 457 if (!This->pUnknown) { 458 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n"); 459 *ppobj = NULL; 460 return E_NOINTERFACE; 461 } 462 } 463 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown); 464 *ppobj = This->pUnknown; 465 return S_OK; 466 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) { 467 IDirectSoundFullDuplexImpl_AddRef(iface); 468 *ppobj = This; 469 return S_OK; 470 } else if (IsEqualIID(riid, &IID_IDirectSound) 471 || IsEqualIID(riid, &IID_IDirectSound8)) { 472 if (!This->pDS8) { 473 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8); 474 if (!This->pDS8) { 475 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n"); 476 *ppobj = NULL; 477 return E_NOINTERFACE; 478 } 479 } 480 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8); 481 *ppobj = This->pDS8; 482 return S_OK; 483 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) { 484 if (!This->pDSC) { 485 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC); 486 if (!This->pDSC) { 487 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n"); 488 *ppobj = NULL; 489 return E_NOINTERFACE; 490 } 491 } 492 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC); 493 *ppobj = This->pDSC; 494 return S_OK; 495 } 496 497 return E_NOINTERFACE; 498 } 499 500 static ULONG WINAPI 501 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface ) 502 { 503 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; 504 ULONG ref = InterlockedDecrement(&(This->ref)); 505 TRACE("(%p) ref was %d\n", This, ref - 1); 506 507 if (!ref) { 508 if (This->capture_device) 509 IDirectSoundCapture_Release(This->capture_device); 510 if (This->renderer_device) 511 IDirectSound_Release(This->renderer_device); 512 HeapFree( GetProcessHeap(), 0, This ); 513 TRACE("(%p) released\n", This); 514 } 515 return ref; 516 } 517 518 static HRESULT WINAPI 519 IDirectSoundFullDuplexImpl_Initialize( 520 LPDIRECTSOUNDFULLDUPLEX iface, 521 LPCGUID pCaptureGuid, 522 LPCGUID pRendererGuid, 523 LPCDSCBUFFERDESC lpDscBufferDesc, 524 LPCDSBUFFERDESC lpDsBufferDesc, 525 HWND hWnd, 526 DWORD dwLevel, 527 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, 528 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 ) 529 { 530 HRESULT hr; 531 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; 532 533 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, 534 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid), 535 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel, 536 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8); 537 538 if (!lplpDirectSoundCaptureBuffer8 || !lplpDirectSoundBuffer8) 539 return E_INVALIDARG; 540 541 if (This->renderer_device != NULL || This->capture_device != NULL) { 542 WARN("already initialized\n"); 543 *lplpDirectSoundCaptureBuffer8 = NULL; 544 *lplpDirectSoundBuffer8 = NULL; 545 return DSERR_ALREADYINITIALIZED; 546 } 547 548 hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device); 549 if (SUCCEEDED(hr)) 550 hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid); 551 if (hr != DS_OK) { 552 WARN("DirectSoundDevice_Initialize() failed\n"); 553 *lplpDirectSoundCaptureBuffer8 = NULL; 554 *lplpDirectSoundBuffer8 = NULL; 555 return hr; 556 } 557 558 IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel); 559 560 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc, 561 (IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL); 562 if (hr != DS_OK) { 563 WARN("IDirectSoundBufferImpl_Create() failed\n"); 564 *lplpDirectSoundCaptureBuffer8 = NULL; 565 *lplpDirectSoundBuffer8 = NULL; 566 return hr; 567 } 568 569 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device); 570 if (SUCCEEDED(hr)) 571 hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid); 572 if (hr != DS_OK) { 573 WARN("DirectSoundCaptureDevice_Initialize() failed\n"); 574 *lplpDirectSoundCaptureBuffer8 = NULL; 575 *lplpDirectSoundBuffer8 = NULL; 576 return hr; 577 } 578 579 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device, 580 lpDscBufferDesc, 581 (IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8, 582 NULL); 583 if (hr != DS_OK) { 584 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n"); 585 *lplpDirectSoundCaptureBuffer8 = NULL; 586 *lplpDirectSoundBuffer8 = NULL; 587 return hr; 588 } 589 590 return hr; 591 } 592 593 static const IDirectSoundFullDuplexVtbl dsfdvt = 594 { 595 /* IUnknown methods */ 596 IDirectSoundFullDuplexImpl_QueryInterface, 597 IDirectSoundFullDuplexImpl_AddRef, 598 IDirectSoundFullDuplexImpl_Release, 599 600 /* IDirectSoundFullDuplex methods */ 601 IDirectSoundFullDuplexImpl_Initialize 602 }; 603 604 HRESULT DSOUND_FullDuplexCreate( 605 REFIID riid, 606 LPDIRECTSOUNDFULLDUPLEX* ppDSFD) 607 { 608 IDirectSoundFullDuplexImpl *This = NULL; 609 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD); 610 611 if (ppDSFD == NULL) { 612 WARN("invalid parameter: ppDSFD == NULL\n"); 613 return DSERR_INVALIDPARAM; 614 } 615 616 if (!IsEqualIID(riid, &IID_IUnknown) && 617 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) { 618 *ppDSFD = 0; 619 return E_NOINTERFACE; 620 } 621 622 /* Get dsound configuration */ 623 setup_dsound_options(); 624 625 This = HeapAlloc(GetProcessHeap(), 626 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl)); 627 628 if (This == NULL) { 629 WARN("out of memory\n"); 630 *ppDSFD = NULL; 631 return DSERR_OUTOFMEMORY; 632 } 633 634 This->lpVtbl = &dsfdvt; 635 This->ref = 1; 636 This->capture_device = NULL; 637 This->renderer_device = NULL; 638 639 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This; 640 641 return DS_OK; 642 } 643 644 /*************************************************************************** 645 * DirectSoundFullDuplexCreate [DSOUND.10] 646 * 647 * Create and initialize a DirectSoundFullDuplex interface. 648 * 649 * PARAMS 650 * pcGuidCaptureDevice [I] Address of sound capture device GUID. 651 * pcGuidRenderDevice [I] Address of sound render device GUID. 652 * pcDSCBufferDesc [I] Address of capture buffer description. 653 * pcDSBufferDesc [I] Address of render buffer description. 654 * hWnd [I] Handle to application window. 655 * dwLevel [I] Cooperative level. 656 * ppDSFD [O] Address where full duplex interface returned. 657 * ppDSCBuffer8 [0] Address where capture buffer interface returned. 658 * ppDSBuffer8 [0] Address where render buffer interface returned. 659 * pUnkOuter [I] Must be NULL. 660 * 661 * RETURNS 662 * Success: DS_OK 663 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM, 664 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER 665 */ 666 HRESULT WINAPI 667 DirectSoundFullDuplexCreate( 668 LPCGUID pcGuidCaptureDevice, 669 LPCGUID pcGuidRenderDevice, 670 LPCDSCBUFFERDESC pcDSCBufferDesc, 671 LPCDSBUFFERDESC pcDSBufferDesc, 672 HWND hWnd, 673 DWORD dwLevel, 674 LPDIRECTSOUNDFULLDUPLEX *ppDSFD, 675 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, 676 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, 677 LPUNKNOWN pUnkOuter) 678 { 679 HRESULT hres; 680 IDirectSoundFullDuplexImpl *This = NULL; 681 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", 682 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice), 683 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8, 684 ppDSBuffer8, pUnkOuter); 685 686 if (pUnkOuter) { 687 WARN("pUnkOuter != 0\n"); 688 *ppDSFD = NULL; 689 return DSERR_NOAGGREGATION; 690 } 691 692 if (pcDSCBufferDesc == NULL) { 693 WARN("invalid parameter: pcDSCBufferDesc == NULL\n"); 694 *ppDSFD = NULL; 695 return DSERR_INVALIDPARAM; 696 } 697 698 if (pcDSBufferDesc == NULL) { 699 WARN("invalid parameter: pcDSBufferDesc == NULL\n"); 700 *ppDSFD = NULL; 701 return DSERR_INVALIDPARAM; 702 } 703 704 if (ppDSFD == NULL) { 705 WARN("invalid parameter: ppDSFD == NULL\n"); 706 return DSERR_INVALIDPARAM; 707 } 708 709 if (ppDSCBuffer8 == NULL) { 710 WARN("invalid parameter: ppDSCBuffer8 == NULL\n"); 711 *ppDSFD = NULL; 712 return DSERR_INVALIDPARAM; 713 } 714 715 if (ppDSBuffer8 == NULL) { 716 WARN("invalid parameter: ppDSBuffer8 == NULL\n"); 717 *ppDSFD = NULL; 718 return DSERR_INVALIDPARAM; 719 } 720 721 hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This); 722 if (FAILED(hres)) return hres; 723 724 hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This, 725 pcGuidCaptureDevice, 726 pcGuidRenderDevice, 727 pcDSCBufferDesc, 728 pcDSBufferDesc, 729 hWnd, dwLevel, ppDSCBuffer8, 730 ppDSBuffer8); 731 if (hres != DS_OK) { 732 IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This); 733 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n"); 734 *ppDSFD = NULL; 735 } else 736 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This; 737 738 return hres; 739 } 740