1 /* DirectSound 2 * 3 * Copyright 1998 Marcus Meissner 4 * Copyright 1998 Rob Riggs 5 * Copyright 2000-2002 TransGaming Technologies, Inc. 6 * Copyright 2004 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 * IDirectSound COM components 27 */ 28 struct IDirectSound_IUnknown { 29 const IUnknownVtbl *lpVtbl; 30 LONG ref; 31 LPDIRECTSOUND8 pds; 32 }; 33 34 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk); 35 36 struct IDirectSound_IDirectSound { 37 const IDirectSoundVtbl *lpVtbl; 38 LONG ref; 39 LPDIRECTSOUND8 pds; 40 }; 41 42 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds); 43 44 /***************************************************************************** 45 * IDirectSound8 COM components 46 */ 47 struct IDirectSound8_IUnknown { 48 const IUnknownVtbl *lpVtbl; 49 LONG ref; 50 LPDIRECTSOUND8 pds; 51 }; 52 53 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk); 54 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface); 55 56 struct IDirectSound8_IDirectSound { 57 const IDirectSoundVtbl *lpVtbl; 58 LONG ref; 59 LPDIRECTSOUND8 pds; 60 }; 61 62 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds); 63 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface); 64 65 struct IDirectSound8_IDirectSound8 { 66 const IDirectSound8Vtbl *lpVtbl; 67 LONG ref; 68 LPDIRECTSOUND8 pds; 69 }; 70 71 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds); 72 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface); 73 74 /***************************************************************************** 75 * IDirectSound implementation structure 76 */ 77 struct IDirectSoundImpl 78 { 79 LONG ref; 80 81 DirectSoundDevice *device; 82 LPUNKNOWN pUnknown; 83 LPDIRECTSOUND pDS; 84 LPDIRECTSOUND8 pDS8; 85 }; 86 87 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds); 88 89 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface); 90 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface); 91 92 const char * dumpCooperativeLevel(DWORD level) 93 { 94 #define LE(x) case x: return #x 95 switch (level) { 96 LE(DSSCL_NORMAL); 97 LE(DSSCL_PRIORITY); 98 LE(DSSCL_EXCLUSIVE); 99 LE(DSSCL_WRITEPRIMARY); 100 } 101 #undef LE 102 return wine_dbg_sprintf("Unknown(%08x)", level); 103 } 104 105 static void _dump_DSCAPS(DWORD xmask) { 106 struct { 107 DWORD mask; 108 const char *name; 109 } flags[] = { 110 #define FE(x) { x, #x }, 111 FE(DSCAPS_PRIMARYMONO) 112 FE(DSCAPS_PRIMARYSTEREO) 113 FE(DSCAPS_PRIMARY8BIT) 114 FE(DSCAPS_PRIMARY16BIT) 115 FE(DSCAPS_CONTINUOUSRATE) 116 FE(DSCAPS_EMULDRIVER) 117 FE(DSCAPS_CERTIFIED) 118 FE(DSCAPS_SECONDARYMONO) 119 FE(DSCAPS_SECONDARYSTEREO) 120 FE(DSCAPS_SECONDARY8BIT) 121 FE(DSCAPS_SECONDARY16BIT) 122 #undef FE 123 }; 124 unsigned int i; 125 126 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++) 127 if ((flags[i].mask & xmask) == flags[i].mask) 128 TRACE("%s ",flags[i].name); 129 } 130 131 static void _dump_DSBCAPS(DWORD xmask) { 132 struct { 133 DWORD mask; 134 const char *name; 135 } flags[] = { 136 #define FE(x) { x, #x }, 137 FE(DSBCAPS_PRIMARYBUFFER) 138 FE(DSBCAPS_STATIC) 139 FE(DSBCAPS_LOCHARDWARE) 140 FE(DSBCAPS_LOCSOFTWARE) 141 FE(DSBCAPS_CTRL3D) 142 FE(DSBCAPS_CTRLFREQUENCY) 143 FE(DSBCAPS_CTRLPAN) 144 FE(DSBCAPS_CTRLVOLUME) 145 FE(DSBCAPS_CTRLPOSITIONNOTIFY) 146 FE(DSBCAPS_STICKYFOCUS) 147 FE(DSBCAPS_GLOBALFOCUS) 148 FE(DSBCAPS_GETCURRENTPOSITION2) 149 FE(DSBCAPS_MUTE3DATMAXDISTANCE) 150 #undef FE 151 }; 152 unsigned int i; 153 154 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++) 155 if ((flags[i].mask & xmask) == flags[i].mask) 156 TRACE("%s ",flags[i].name); 157 } 158 159 /******************************************************************************* 160 * IDirectSoundImpl_DirectSound 161 */ 162 static HRESULT DSOUND_QueryInterface( 163 LPDIRECTSOUND8 iface, 164 REFIID riid, 165 LPVOID * ppobj) 166 { 167 IDirectSoundImpl *This = (IDirectSoundImpl *)iface; 168 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 169 170 if (ppobj == NULL) { 171 WARN("invalid parameter\n"); 172 return E_INVALIDARG; 173 } 174 175 if (IsEqualIID(riid, &IID_IUnknown)) { 176 if (!This->pUnknown) { 177 IDirectSound_IUnknown_Create(iface, &This->pUnknown); 178 if (!This->pUnknown) { 179 WARN("IDirectSound_IUnknown_Create() failed\n"); 180 *ppobj = NULL; 181 return E_NOINTERFACE; 182 } 183 } 184 IDirectSound_IUnknown_AddRef(This->pUnknown); 185 *ppobj = This->pUnknown; 186 return S_OK; 187 } else if (IsEqualIID(riid, &IID_IDirectSound)) { 188 if (!This->pDS) { 189 IDirectSound_IDirectSound_Create(iface, &This->pDS); 190 if (!This->pDS) { 191 WARN("IDirectSound_IDirectSound_Create() failed\n"); 192 *ppobj = NULL; 193 return E_NOINTERFACE; 194 } 195 } 196 IDirectSound_IDirectSound_AddRef(This->pDS); 197 *ppobj = This->pDS; 198 return S_OK; 199 } 200 201 *ppobj = NULL; 202 WARN("Unknown IID %s\n",debugstr_guid(riid)); 203 return E_NOINTERFACE; 204 } 205 206 static HRESULT DSOUND_QueryInterface8( 207 LPDIRECTSOUND8 iface, 208 REFIID riid, 209 LPVOID * ppobj) 210 { 211 IDirectSoundImpl *This = (IDirectSoundImpl *)iface; 212 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 213 214 if (ppobj == NULL) { 215 WARN("invalid parameter\n"); 216 return E_INVALIDARG; 217 } 218 219 if (IsEqualIID(riid, &IID_IUnknown)) { 220 if (!This->pUnknown) { 221 IDirectSound8_IUnknown_Create(iface, &This->pUnknown); 222 if (!This->pUnknown) { 223 WARN("IDirectSound8_IUnknown_Create() failed\n"); 224 *ppobj = NULL; 225 return E_NOINTERFACE; 226 } 227 } 228 IDirectSound8_IUnknown_AddRef(This->pUnknown); 229 *ppobj = This->pUnknown; 230 return S_OK; 231 } else if (IsEqualIID(riid, &IID_IDirectSound)) { 232 if (!This->pDS) { 233 IDirectSound8_IDirectSound_Create(iface, &This->pDS); 234 if (!This->pDS) { 235 WARN("IDirectSound8_IDirectSound_Create() failed\n"); 236 *ppobj = NULL; 237 return E_NOINTERFACE; 238 } 239 } 240 IDirectSound8_IDirectSound_AddRef(This->pDS); 241 *ppobj = This->pDS; 242 return S_OK; 243 } else if (IsEqualIID(riid, &IID_IDirectSound8)) { 244 if (!This->pDS8) { 245 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8); 246 if (!This->pDS8) { 247 WARN("IDirectSound8_IDirectSound8_Create() failed\n"); 248 *ppobj = NULL; 249 return E_NOINTERFACE; 250 } 251 } 252 IDirectSound8_IDirectSound8_AddRef(This->pDS8); 253 *ppobj = This->pDS8; 254 return S_OK; 255 } 256 257 *ppobj = NULL; 258 WARN("Unknown IID %s\n",debugstr_guid(riid)); 259 return E_NOINTERFACE; 260 } 261 262 static ULONG IDirectSoundImpl_AddRef( 263 LPDIRECTSOUND8 iface) 264 { 265 IDirectSoundImpl *This = (IDirectSoundImpl *)iface; 266 ULONG ref = InterlockedIncrement(&(This->ref)); 267 TRACE("(%p) ref was %d\n", This, ref - 1); 268 return ref; 269 } 270 271 static ULONG IDirectSoundImpl_Release( 272 LPDIRECTSOUND8 iface) 273 { 274 IDirectSoundImpl *This = (IDirectSoundImpl *)iface; 275 ULONG ref = InterlockedDecrement(&(This->ref)); 276 TRACE("(%p) ref was %d\n", This, ref + 1); 277 278 if (!ref) { 279 if (This->device) 280 DirectSoundDevice_Release(This->device); 281 HeapFree(GetProcessHeap(),0,This); 282 TRACE("(%p) released\n", This); 283 } 284 return ref; 285 } 286 287 static HRESULT IDirectSoundImpl_Create( 288 LPDIRECTSOUND8 * ppDS) 289 { 290 IDirectSoundImpl* pDS; 291 TRACE("(%p)\n",ppDS); 292 293 /* Allocate memory */ 294 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl)); 295 if (pDS == NULL) { 296 WARN("out of memory\n"); 297 *ppDS = NULL; 298 return DSERR_OUTOFMEMORY; 299 } 300 301 pDS->ref = 0; 302 pDS->device = NULL; 303 304 *ppDS = (LPDIRECTSOUND8)pDS; 305 306 return DS_OK; 307 } 308 309 /******************************************************************************* 310 * IDirectSound_IUnknown 311 */ 312 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface( 313 LPUNKNOWN iface, 314 REFIID riid, 315 LPVOID * ppobj) 316 { 317 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 318 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 319 return DSOUND_QueryInterface(This->pds, riid, ppobj); 320 } 321 322 static ULONG WINAPI IDirectSound_IUnknown_AddRef( 323 LPUNKNOWN iface) 324 { 325 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 326 ULONG ref = InterlockedIncrement(&(This->ref)); 327 TRACE("(%p) ref was %d\n", This, ref - 1); 328 return ref; 329 } 330 331 static ULONG WINAPI IDirectSound_IUnknown_Release( 332 LPUNKNOWN iface) 333 { 334 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 335 ULONG ref = InterlockedDecrement(&(This->ref)); 336 TRACE("(%p) ref was %d\n", This, ref + 1); 337 if (!ref) { 338 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL; 339 IDirectSoundImpl_Release(This->pds); 340 HeapFree(GetProcessHeap(), 0, This); 341 TRACE("(%p) released\n", This); 342 } 343 return ref; 344 } 345 346 static const IUnknownVtbl DirectSound_Unknown_Vtbl = 347 { 348 IDirectSound_IUnknown_QueryInterface, 349 IDirectSound_IUnknown_AddRef, 350 IDirectSound_IUnknown_Release 351 }; 352 353 static HRESULT IDirectSound_IUnknown_Create( 354 LPDIRECTSOUND8 pds, 355 LPUNKNOWN * ppunk) 356 { 357 IDirectSound_IUnknown * pdsunk; 358 TRACE("(%p,%p)\n",pds,ppunk); 359 360 if (ppunk == NULL) { 361 ERR("invalid parameter: ppunk == NULL\n"); 362 return DSERR_INVALIDPARAM; 363 } 364 365 if (pds == NULL) { 366 ERR("invalid parameter: pds == NULL\n"); 367 *ppunk = NULL; 368 return DSERR_INVALIDPARAM; 369 } 370 371 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); 372 if (pdsunk == NULL) { 373 WARN("out of memory\n"); 374 *ppunk = NULL; 375 return DSERR_OUTOFMEMORY; 376 } 377 378 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl; 379 pdsunk->ref = 0; 380 pdsunk->pds = pds; 381 382 IDirectSoundImpl_AddRef(pds); 383 *ppunk = (LPUNKNOWN)pdsunk; 384 385 return DS_OK; 386 } 387 388 /******************************************************************************* 389 * IDirectSound_IDirectSound 390 */ 391 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface( 392 LPDIRECTSOUND iface, 393 REFIID riid, 394 LPVOID * ppobj) 395 { 396 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 397 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 398 return DSOUND_QueryInterface(This->pds, riid, ppobj); 399 } 400 401 static ULONG WINAPI IDirectSound_IDirectSound_AddRef( 402 LPDIRECTSOUND iface) 403 { 404 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 405 ULONG ref = InterlockedIncrement(&(This->ref)); 406 TRACE("(%p) ref was %d\n", This, ref - 1); 407 return ref; 408 } 409 410 static ULONG WINAPI IDirectSound_IDirectSound_Release( 411 LPDIRECTSOUND iface) 412 { 413 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 414 ULONG ref = InterlockedDecrement(&(This->ref)); 415 TRACE("(%p) ref was %d\n", This, ref + 1); 416 if (!ref) { 417 ((IDirectSoundImpl*)This->pds)->pDS = NULL; 418 IDirectSoundImpl_Release(This->pds); 419 HeapFree(GetProcessHeap(), 0, This); 420 TRACE("(%p) released\n", This); 421 } 422 return ref; 423 } 424 425 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer( 426 LPDIRECTSOUND iface, 427 LPCDSBUFFERDESC dsbd, 428 LPLPDIRECTSOUNDBUFFER ppdsb, 429 LPUNKNOWN lpunk) 430 { 431 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 432 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); 433 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE); 434 } 435 436 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps( 437 LPDIRECTSOUND iface, 438 LPDSCAPS lpDSCaps) 439 { 440 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 441 TRACE("(%p,%p)\n",This,lpDSCaps); 442 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); 443 } 444 445 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer( 446 LPDIRECTSOUND iface, 447 LPDIRECTSOUNDBUFFER psb, 448 LPLPDIRECTSOUNDBUFFER ppdsb) 449 { 450 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 451 TRACE("(%p,%p,%p)\n",This,psb,ppdsb); 452 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); 453 } 454 455 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel( 456 LPDIRECTSOUND iface, 457 HWND hwnd, 458 DWORD level) 459 { 460 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 461 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); 462 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); 463 } 464 465 static HRESULT WINAPI IDirectSound_IDirectSound_Compact( 466 LPDIRECTSOUND iface) 467 { 468 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 469 TRACE("(%p)\n", This); 470 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); 471 } 472 473 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig( 474 LPDIRECTSOUND iface, 475 LPDWORD lpdwSpeakerConfig) 476 { 477 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 478 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); 479 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); 480 } 481 482 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig( 483 LPDIRECTSOUND iface, 484 DWORD config) 485 { 486 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 487 TRACE("(%p,0x%08x)\n",This,config); 488 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); 489 } 490 491 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize( 492 LPDIRECTSOUND iface, 493 LPCGUID lpcGuid) 494 { 495 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; 496 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); 497 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); 498 } 499 500 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl = 501 { 502 IDirectSound_IDirectSound_QueryInterface, 503 IDirectSound_IDirectSound_AddRef, 504 IDirectSound_IDirectSound_Release, 505 IDirectSound_IDirectSound_CreateSoundBuffer, 506 IDirectSound_IDirectSound_GetCaps, 507 IDirectSound_IDirectSound_DuplicateSoundBuffer, 508 IDirectSound_IDirectSound_SetCooperativeLevel, 509 IDirectSound_IDirectSound_Compact, 510 IDirectSound_IDirectSound_GetSpeakerConfig, 511 IDirectSound_IDirectSound_SetSpeakerConfig, 512 IDirectSound_IDirectSound_Initialize 513 }; 514 515 static HRESULT IDirectSound_IDirectSound_Create( 516 LPDIRECTSOUND8 pds, 517 LPDIRECTSOUND * ppds) 518 { 519 IDirectSound_IDirectSound * pdsds; 520 TRACE("(%p,%p)\n",pds,ppds); 521 522 if (ppds == NULL) { 523 ERR("invalid parameter: ppds == NULL\n"); 524 return DSERR_INVALIDPARAM; 525 } 526 527 if (pds == NULL) { 528 ERR("invalid parameter: pds == NULL\n"); 529 *ppds = NULL; 530 return DSERR_INVALIDPARAM; 531 } 532 533 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); 534 if (pdsds == NULL) { 535 WARN("out of memory\n"); 536 *ppds = NULL; 537 return DSERR_OUTOFMEMORY; 538 } 539 540 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl; 541 pdsds->ref = 0; 542 pdsds->pds = pds; 543 544 IDirectSoundImpl_AddRef(pds); 545 *ppds = (LPDIRECTSOUND)pdsds; 546 547 return DS_OK; 548 } 549 550 /******************************************************************************* 551 * IDirectSound8_IUnknown 552 */ 553 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface( 554 LPUNKNOWN iface, 555 REFIID riid, 556 LPVOID * ppobj) 557 { 558 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 559 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 560 return DSOUND_QueryInterface8(This->pds, riid, ppobj); 561 } 562 563 static ULONG WINAPI IDirectSound8_IUnknown_AddRef( 564 LPUNKNOWN iface) 565 { 566 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 567 ULONG ref = InterlockedIncrement(&(This->ref)); 568 TRACE("(%p) ref was %d\n", This, ref - 1); 569 return ref; 570 } 571 572 static ULONG WINAPI IDirectSound8_IUnknown_Release( 573 LPUNKNOWN iface) 574 { 575 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; 576 ULONG ref = InterlockedDecrement(&(This->ref)); 577 TRACE("(%p) ref was %d\n", This, ref + 1); 578 if (!ref) { 579 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL; 580 IDirectSoundImpl_Release(This->pds); 581 HeapFree(GetProcessHeap(), 0, This); 582 TRACE("(%p) released\n", This); 583 } 584 return ref; 585 } 586 587 static const IUnknownVtbl DirectSound8_Unknown_Vtbl = 588 { 589 IDirectSound8_IUnknown_QueryInterface, 590 IDirectSound8_IUnknown_AddRef, 591 IDirectSound8_IUnknown_Release 592 }; 593 594 static HRESULT IDirectSound8_IUnknown_Create( 595 LPDIRECTSOUND8 pds, 596 LPUNKNOWN * ppunk) 597 { 598 IDirectSound8_IUnknown * pdsunk; 599 TRACE("(%p,%p)\n",pds,ppunk); 600 601 if (ppunk == NULL) { 602 ERR("invalid parameter: ppunk == NULL\n"); 603 return DSERR_INVALIDPARAM; 604 } 605 606 if (pds == NULL) { 607 ERR("invalid parameter: pds == NULL\n"); 608 *ppunk = NULL; 609 return DSERR_INVALIDPARAM; 610 } 611 612 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); 613 if (pdsunk == NULL) { 614 WARN("out of memory\n"); 615 *ppunk = NULL; 616 return DSERR_OUTOFMEMORY; 617 } 618 619 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl; 620 pdsunk->ref = 0; 621 pdsunk->pds = pds; 622 623 IDirectSoundImpl_AddRef(pds); 624 *ppunk = (LPUNKNOWN)pdsunk; 625 626 return DS_OK; 627 } 628 629 /******************************************************************************* 630 * IDirectSound8_IDirectSound 631 */ 632 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface( 633 LPDIRECTSOUND iface, 634 REFIID riid, 635 LPVOID * ppobj) 636 { 637 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 638 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 639 return DSOUND_QueryInterface8(This->pds, riid, ppobj); 640 } 641 642 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef( 643 LPDIRECTSOUND iface) 644 { 645 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 646 ULONG ref = InterlockedIncrement(&(This->ref)); 647 TRACE("(%p) ref was %d\n", This, ref - 1); 648 return ref; 649 } 650 651 static ULONG WINAPI IDirectSound8_IDirectSound_Release( 652 LPDIRECTSOUND iface) 653 { 654 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 655 ULONG ref = InterlockedDecrement(&(This->ref)); 656 TRACE("(%p) ref was %d\n", This, ref + 1); 657 if (!ref) { 658 ((IDirectSoundImpl*)This->pds)->pDS = NULL; 659 IDirectSoundImpl_Release(This->pds); 660 HeapFree(GetProcessHeap(), 0, This); 661 TRACE("(%p) released\n", This); 662 } 663 return ref; 664 } 665 666 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer( 667 LPDIRECTSOUND iface, 668 LPCDSBUFFERDESC dsbd, 669 LPLPDIRECTSOUNDBUFFER ppdsb, 670 LPUNKNOWN lpunk) 671 { 672 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 673 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); 674 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE); 675 } 676 677 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps( 678 LPDIRECTSOUND iface, 679 LPDSCAPS lpDSCaps) 680 { 681 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 682 TRACE("(%p,%p)\n",This,lpDSCaps); 683 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); 684 } 685 686 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer( 687 LPDIRECTSOUND iface, 688 LPDIRECTSOUNDBUFFER psb, 689 LPLPDIRECTSOUNDBUFFER ppdsb) 690 { 691 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 692 TRACE("(%p,%p,%p)\n",This,psb,ppdsb); 693 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); 694 } 695 696 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel( 697 LPDIRECTSOUND iface, 698 HWND hwnd, 699 DWORD level) 700 { 701 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 702 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); 703 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); 704 } 705 706 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact( 707 LPDIRECTSOUND iface) 708 { 709 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 710 TRACE("(%p)\n", This); 711 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); 712 } 713 714 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig( 715 LPDIRECTSOUND iface, 716 LPDWORD lpdwSpeakerConfig) 717 { 718 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 719 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); 720 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); 721 } 722 723 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig( 724 LPDIRECTSOUND iface, 725 DWORD config) 726 { 727 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 728 TRACE("(%p,0x%08x)\n",This,config); 729 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); 730 } 731 732 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize( 733 LPDIRECTSOUND iface, 734 LPCGUID lpcGuid) 735 { 736 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 737 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); 738 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); 739 } 740 741 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl = 742 { 743 IDirectSound8_IDirectSound_QueryInterface, 744 IDirectSound8_IDirectSound_AddRef, 745 IDirectSound8_IDirectSound_Release, 746 IDirectSound8_IDirectSound_CreateSoundBuffer, 747 IDirectSound8_IDirectSound_GetCaps, 748 IDirectSound8_IDirectSound_DuplicateSoundBuffer, 749 IDirectSound8_IDirectSound_SetCooperativeLevel, 750 IDirectSound8_IDirectSound_Compact, 751 IDirectSound8_IDirectSound_GetSpeakerConfig, 752 IDirectSound8_IDirectSound_SetSpeakerConfig, 753 IDirectSound8_IDirectSound_Initialize 754 }; 755 756 static HRESULT IDirectSound8_IDirectSound_Create( 757 LPDIRECTSOUND8 pds, 758 LPDIRECTSOUND * ppds) 759 { 760 IDirectSound8_IDirectSound * pdsds; 761 TRACE("(%p,%p)\n",pds,ppds); 762 763 if (ppds == NULL) { 764 ERR("invalid parameter: ppds == NULL\n"); 765 return DSERR_INVALIDPARAM; 766 } 767 768 if (pds == NULL) { 769 ERR("invalid parameter: pds == NULL\n"); 770 *ppds = NULL; 771 return DSERR_INVALIDPARAM; 772 } 773 774 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); 775 if (pdsds == NULL) { 776 WARN("out of memory\n"); 777 *ppds = NULL; 778 return DSERR_OUTOFMEMORY; 779 } 780 781 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl; 782 pdsds->ref = 0; 783 pdsds->pds = pds; 784 785 IDirectSoundImpl_AddRef(pds); 786 *ppds = (LPDIRECTSOUND)pdsds; 787 788 return DS_OK; 789 } 790 791 /******************************************************************************* 792 * IDirectSound8_IDirectSound8 793 */ 794 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface( 795 LPDIRECTSOUND8 iface, 796 REFIID riid, 797 LPVOID * ppobj) 798 { 799 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 800 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); 801 return DSOUND_QueryInterface8(This->pds, riid, ppobj); 802 } 803 804 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef( 805 LPDIRECTSOUND8 iface) 806 { 807 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 808 ULONG ref = InterlockedIncrement(&(This->ref)); 809 TRACE("(%p) ref was %d\n", This, ref - 1); 810 return ref; 811 } 812 813 static ULONG WINAPI IDirectSound8_IDirectSound8_Release( 814 LPDIRECTSOUND8 iface) 815 { 816 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 817 ULONG ref = InterlockedDecrement(&(This->ref)); 818 TRACE("(%p) ref was %d\n", This, ref + 1); 819 if (!ref) { 820 ((IDirectSoundImpl*)This->pds)->pDS8 = NULL; 821 IDirectSoundImpl_Release(This->pds); 822 HeapFree(GetProcessHeap(), 0, This); 823 TRACE("(%p) released\n", This); 824 } 825 return ref; 826 } 827 828 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer( 829 LPDIRECTSOUND8 iface, 830 LPCDSBUFFERDESC dsbd, 831 LPLPDIRECTSOUNDBUFFER ppdsb, 832 LPUNKNOWN lpunk) 833 { 834 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 835 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); 836 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE); 837 } 838 839 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps( 840 LPDIRECTSOUND8 iface, 841 LPDSCAPS lpDSCaps) 842 { 843 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; 844 TRACE("(%p,%p)\n",This,lpDSCaps); 845 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); 846 } 847 848 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer( 849 LPDIRECTSOUND8 iface, 850 LPDIRECTSOUNDBUFFER psb, 851 LPLPDIRECTSOUNDBUFFER ppdsb) 852 { 853 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 854 TRACE("(%p,%p,%p)\n",This,psb,ppdsb); 855 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); 856 } 857 858 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel( 859 LPDIRECTSOUND8 iface, 860 HWND hwnd, 861 DWORD level) 862 { 863 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 864 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); 865 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); 866 } 867 868 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact( 869 LPDIRECTSOUND8 iface) 870 { 871 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 872 TRACE("(%p)\n", This); 873 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); 874 } 875 876 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig( 877 LPDIRECTSOUND8 iface, 878 LPDWORD lpdwSpeakerConfig) 879 { 880 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 881 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); 882 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); 883 } 884 885 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig( 886 LPDIRECTSOUND8 iface, 887 DWORD config) 888 { 889 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 890 TRACE("(%p,0x%08x)\n",This,config); 891 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); 892 } 893 894 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize( 895 LPDIRECTSOUND8 iface, 896 LPCGUID lpcGuid) 897 { 898 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 899 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); 900 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); 901 } 902 903 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification( 904 LPDIRECTSOUND8 iface, 905 LPDWORD pdwCertified) 906 { 907 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; 908 TRACE("(%p, %p)\n", This, pdwCertified); 909 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified); 910 } 911 912 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl = 913 { 914 IDirectSound8_IDirectSound8_QueryInterface, 915 IDirectSound8_IDirectSound8_AddRef, 916 IDirectSound8_IDirectSound8_Release, 917 IDirectSound8_IDirectSound8_CreateSoundBuffer, 918 IDirectSound8_IDirectSound8_GetCaps, 919 IDirectSound8_IDirectSound8_DuplicateSoundBuffer, 920 IDirectSound8_IDirectSound8_SetCooperativeLevel, 921 IDirectSound8_IDirectSound8_Compact, 922 IDirectSound8_IDirectSound8_GetSpeakerConfig, 923 IDirectSound8_IDirectSound8_SetSpeakerConfig, 924 IDirectSound8_IDirectSound8_Initialize, 925 IDirectSound8_IDirectSound8_VerifyCertification 926 }; 927 928 static HRESULT IDirectSound8_IDirectSound8_Create( 929 LPDIRECTSOUND8 pds, 930 LPDIRECTSOUND8 * ppds) 931 { 932 IDirectSound8_IDirectSound8 * pdsds; 933 TRACE("(%p,%p)\n",pds,ppds); 934 935 if (ppds == NULL) { 936 ERR("invalid parameter: ppds == NULL\n"); 937 return DSERR_INVALIDPARAM; 938 } 939 940 if (pds == NULL) { 941 ERR("invalid parameter: pds == NULL\n"); 942 *ppds = NULL; 943 return DSERR_INVALIDPARAM; 944 } 945 946 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); 947 if (pdsds == NULL) { 948 WARN("out of memory\n"); 949 *ppds = NULL; 950 return DSERR_OUTOFMEMORY; 951 } 952 953 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl; 954 pdsds->ref = 0; 955 pdsds->pds = pds; 956 957 IDirectSoundImpl_AddRef(pds); 958 *ppds = (LPDIRECTSOUND8)pdsds; 959 960 return DS_OK; 961 } 962 963 HRESULT DSOUND_Create( 964 REFIID riid, 965 LPDIRECTSOUND *ppDS) 966 { 967 LPDIRECTSOUND8 pDS; 968 HRESULT hr; 969 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS); 970 971 if (!IsEqualIID(riid, &IID_IUnknown) && 972 !IsEqualIID(riid, &IID_IDirectSound)) { 973 *ppDS = 0; 974 return E_NOINTERFACE; 975 } 976 977 /* Get dsound configuration */ 978 setup_dsound_options(); 979 980 hr = IDirectSoundImpl_Create(&pDS); 981 if (hr == DS_OK) { 982 hr = IDirectSound_IDirectSound_Create(pDS, ppDS); 983 if (*ppDS) 984 IDirectSound_IDirectSound_AddRef(*ppDS); 985 else { 986 WARN("IDirectSound_IDirectSound_Create failed\n"); 987 IDirectSound8_Release(pDS); 988 } 989 } else { 990 WARN("IDirectSoundImpl_Create failed\n"); 991 *ppDS = 0; 992 } 993 994 return hr; 995 } 996 997 /******************************************************************************* 998 * DirectSoundCreate (DSOUND.1) 999 * 1000 * Creates and initializes a DirectSound interface. 1001 * 1002 * PARAMS 1003 * lpcGUID [I] Address of the GUID that identifies the sound device. 1004 * ppDS [O] Address of a variable to receive the interface pointer. 1005 * pUnkOuter [I] Must be NULL. 1006 * 1007 * RETURNS 1008 * Success: DS_OK 1009 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, 1010 * DSERR_NODRIVER, DSERR_OUTOFMEMORY 1011 */ 1012 HRESULT WINAPI DirectSoundCreate( 1013 LPCGUID lpcGUID, 1014 LPDIRECTSOUND *ppDS, 1015 IUnknown *pUnkOuter) 1016 { 1017 HRESULT hr; 1018 LPDIRECTSOUND pDS; 1019 1020 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); 1021 1022 if (ppDS == NULL) { 1023 WARN("invalid parameter: ppDS == NULL\n"); 1024 return DSERR_INVALIDPARAM; 1025 } 1026 1027 if (pUnkOuter != NULL) { 1028 WARN("invalid parameter: pUnkOuter != NULL\n"); 1029 *ppDS = 0; 1030 return DSERR_INVALIDPARAM; 1031 } 1032 1033 hr = DSOUND_Create(&IID_IDirectSound, &pDS); 1034 if (hr == DS_OK) { 1035 hr = IDirectSound_Initialize(pDS, lpcGUID); 1036 if (hr != DS_OK) { 1037 if (hr != DSERR_ALREADYINITIALIZED) { 1038 IDirectSound_Release(pDS); 1039 pDS = 0; 1040 } else 1041 hr = DS_OK; 1042 } 1043 } 1044 1045 *ppDS = pDS; 1046 1047 return hr; 1048 } 1049 1050 HRESULT DSOUND_Create8( 1051 REFIID riid, 1052 LPDIRECTSOUND8 *ppDS) 1053 { 1054 LPDIRECTSOUND8 pDS; 1055 HRESULT hr; 1056 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS); 1057 1058 if (!IsEqualIID(riid, &IID_IUnknown) && 1059 !IsEqualIID(riid, &IID_IDirectSound) && 1060 !IsEqualIID(riid, &IID_IDirectSound8)) { 1061 *ppDS = 0; 1062 return E_NOINTERFACE; 1063 } 1064 1065 /* Get dsound configuration */ 1066 setup_dsound_options(); 1067 1068 hr = IDirectSoundImpl_Create(&pDS); 1069 if (hr == DS_OK) { 1070 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS); 1071 if (*ppDS) 1072 IDirectSound8_IDirectSound8_AddRef(*ppDS); 1073 else { 1074 WARN("IDirectSound8_IDirectSound8_Create failed\n"); 1075 IDirectSound8_Release(pDS); 1076 } 1077 } else { 1078 WARN("IDirectSoundImpl_Create failed\n"); 1079 *ppDS = 0; 1080 } 1081 1082 return hr; 1083 } 1084 1085 /******************************************************************************* 1086 * DirectSoundCreate8 (DSOUND.11) 1087 * 1088 * Creates and initializes a DirectSound8 interface. 1089 * 1090 * PARAMS 1091 * lpcGUID [I] Address of the GUID that identifies the sound device. 1092 * ppDS [O] Address of a variable to receive the interface pointer. 1093 * pUnkOuter [I] Must be NULL. 1094 * 1095 * RETURNS 1096 * Success: DS_OK 1097 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, 1098 * DSERR_NODRIVER, DSERR_OUTOFMEMORY 1099 */ 1100 HRESULT WINAPI DirectSoundCreate8( 1101 LPCGUID lpcGUID, 1102 LPDIRECTSOUND8 *ppDS, 1103 IUnknown *pUnkOuter) 1104 { 1105 HRESULT hr; 1106 LPDIRECTSOUND8 pDS; 1107 1108 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); 1109 1110 if (ppDS == NULL) { 1111 WARN("invalid parameter: ppDS == NULL\n"); 1112 return DSERR_INVALIDPARAM; 1113 } 1114 1115 if (pUnkOuter != NULL) { 1116 WARN("invalid parameter: pUnkOuter != NULL\n"); 1117 *ppDS = 0; 1118 return DSERR_INVALIDPARAM; 1119 } 1120 1121 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS); 1122 if (hr == DS_OK) { 1123 hr = IDirectSound8_Initialize(pDS, lpcGUID); 1124 if (hr != DS_OK) { 1125 if (hr != DSERR_ALREADYINITIALIZED) { 1126 IDirectSound8_Release(pDS); 1127 pDS = 0; 1128 } else 1129 hr = DS_OK; 1130 } 1131 } 1132 1133 *ppDS = pDS; 1134 1135 return hr; 1136 } 1137 1138 /******************************************************************************* 1139 * DirectSoundDevice 1140 */ 1141 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice) 1142 { 1143 DirectSoundDevice * device; 1144 TRACE("(%p)\n", ppDevice); 1145 1146 /* Allocate memory */ 1147 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice)); 1148 if (device == NULL) { 1149 WARN("out of memory\n"); 1150 return DSERR_OUTOFMEMORY; 1151 } 1152 1153 device->ref = 1; 1154 device->priolevel = DSSCL_NORMAL; 1155 device->state = STATE_STOPPED; 1156 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16); 1157 1158 /* 3D listener initial parameters */ 1159 device->ds3dl.dwSize = sizeof(DS3DLISTENER); 1160 device->ds3dl.vPosition.x = 0.0; 1161 device->ds3dl.vPosition.y = 0.0; 1162 device->ds3dl.vPosition.z = 0.0; 1163 device->ds3dl.vVelocity.x = 0.0; 1164 device->ds3dl.vVelocity.y = 0.0; 1165 device->ds3dl.vVelocity.z = 0.0; 1166 device->ds3dl.vOrientFront.x = 0.0; 1167 device->ds3dl.vOrientFront.y = 0.0; 1168 device->ds3dl.vOrientFront.z = 1.0; 1169 device->ds3dl.vOrientTop.x = 0.0; 1170 device->ds3dl.vOrientTop.y = 1.0; 1171 device->ds3dl.vOrientTop.z = 0.0; 1172 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; 1173 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; 1174 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; 1175 1176 device->prebuf = ds_snd_queue_max; 1177 device->guid = GUID_NULL; 1178 1179 /* Set default wave format (may need it for waveOutOpen) */ 1180 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX)); 1181 if (device->pwfx == NULL) { 1182 WARN("out of memory\n"); 1183 HeapFree(GetProcessHeap(),0,device); 1184 return DSERR_OUTOFMEMORY; 1185 } 1186 1187 /* We rely on the sound driver to return the actual sound format of 1188 * the device if it does not support 22050x8x2 and is given the 1189 * WAVE_DIRECTSOUND flag. 1190 */ 1191 device->pwfx->wFormatTag = WAVE_FORMAT_PCM; 1192 device->pwfx->nSamplesPerSec = ds_default_sample_rate; 1193 device->pwfx->wBitsPerSample = ds_default_bits_per_sample; 1194 device->pwfx->nChannels = 2; 1195 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8; 1196 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign; 1197 device->pwfx->cbSize = 0; 1198 1199 InitializeCriticalSection(&(device->mixlock)); 1200 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock"); 1201 1202 RtlInitializeResource(&(device->buffer_list_lock)); 1203 1204 *ppDevice = device; 1205 1206 return DS_OK; 1207 } 1208 1209 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device) 1210 { 1211 ULONG ref = InterlockedIncrement(&(device->ref)); 1212 TRACE("(%p) ref was %d\n", device, ref - 1); 1213 return ref; 1214 } 1215 1216 ULONG DirectSoundDevice_Release(DirectSoundDevice * device) 1217 { 1218 HRESULT hr; 1219 ULONG ref = InterlockedDecrement(&(device->ref)); 1220 TRACE("(%p) ref was %u\n", device, ref + 1); 1221 if (!ref) { 1222 int i; 1223 timeKillEvent(device->timerID); 1224 timeEndPeriod(DS_TIME_RES); 1225 1226 /* The kill event should have allowed the timer process to expire 1227 * but try to grab the lock just in case. Can't hold lock because 1228 * IDirectSoundBufferImpl_Destroy also grabs the lock */ 1229 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE); 1230 RtlReleaseResource(&(device->buffer_list_lock)); 1231 1232 /* It is allowed to release this object even when buffers are playing */ 1233 if (device->buffers) { 1234 WARN("%d secondary buffers not released\n", device->nrofbuffers); 1235 for( i=0;i<device->nrofbuffers;i++) 1236 IDirectSoundBufferImpl_Destroy(device->buffers[i]); 1237 } 1238 1239 if (device->primary) { 1240 WARN("primary buffer not released\n"); 1241 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary); 1242 } 1243 1244 hr = DSOUND_PrimaryDestroy(device); 1245 if (hr != DS_OK) 1246 WARN("DSOUND_PrimaryDestroy failed\n"); 1247 1248 if (device->driver) 1249 IDsDriver_Close(device->driver); 1250 1251 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) 1252 waveOutClose(device->hwo); 1253 1254 if (device->driver) 1255 IDsDriver_Release(device->driver); 1256 1257 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL; 1258 1259 HeapFree(GetProcessHeap(), 0, device->tmp_buffer); 1260 HeapFree(GetProcessHeap(), 0, device->mix_buffer); 1261 if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) 1262 HeapFree(GetProcessHeap(), 0, device->buffer); 1263 RtlDeleteResource(&device->buffer_list_lock); 1264 device->mixlock.DebugInfo->Spare[0] = 0; 1265 DeleteCriticalSection(&device->mixlock); 1266 HeapFree(GetProcessHeap(),0,device); 1267 TRACE("(%p) released\n", device); 1268 } 1269 return ref; 1270 } 1271 1272 HRESULT DirectSoundDevice_GetCaps( 1273 DirectSoundDevice * device, 1274 LPDSCAPS lpDSCaps) 1275 { 1276 TRACE("(%p,%p)\n",device,lpDSCaps); 1277 1278 if (device == NULL) { 1279 WARN("not initialized\n"); 1280 return DSERR_UNINITIALIZED; 1281 } 1282 1283 if (lpDSCaps == NULL) { 1284 WARN("invalid parameter: lpDSCaps = NULL\n"); 1285 return DSERR_INVALIDPARAM; 1286 } 1287 1288 /* check if there is enough room */ 1289 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) { 1290 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize); 1291 return DSERR_INVALIDPARAM; 1292 } 1293 1294 lpDSCaps->dwFlags = device->drvcaps.dwFlags; 1295 if (TRACE_ON(dsound)) { 1296 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags); 1297 _dump_DSCAPS(lpDSCaps->dwFlags); 1298 TRACE(")\n"); 1299 } 1300 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate; 1301 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate; 1302 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers; 1303 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers; 1304 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers; 1305 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers; 1306 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers; 1307 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers; 1308 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers; 1309 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers; 1310 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers; 1311 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers; 1312 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers; 1313 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers; 1314 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers; 1315 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes; 1316 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes; 1317 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes; 1318 1319 /* driver doesn't have these */ 1320 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */ 1321 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */ 1322 1323 return DS_OK; 1324 } 1325 1326 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID) 1327 { 1328 HRESULT hr = DS_OK; 1329 unsigned wod, wodn; 1330 BOOLEAN found = FALSE; 1331 GUID devGUID; 1332 DirectSoundDevice * device = *ppDevice; 1333 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID)); 1334 1335 if (*ppDevice != NULL) { 1336 WARN("already initialized\n"); 1337 return DSERR_ALREADYINITIALIZED; 1338 } 1339 1340 /* Default device? */ 1341 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL)) 1342 lpcGUID = &DSDEVID_DefaultPlayback; 1343 1344 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) { 1345 WARN("invalid parameter: lpcGUID\n"); 1346 return DSERR_INVALIDPARAM; 1347 } 1348 1349 /* Enumerate WINMM audio devices and find the one we want */ 1350 wodn = waveOutGetNumDevs(); 1351 if (!wodn) { 1352 WARN("no driver\n"); 1353 return DSERR_NODRIVER; 1354 } 1355 1356 for (wod=0; wod<wodn; wod++) { 1357 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) { 1358 found = TRUE; 1359 break; 1360 } 1361 } 1362 1363 if (found == FALSE) { 1364 WARN("No device found matching given ID!\n"); 1365 return DSERR_NODRIVER; 1366 } 1367 1368 if (DSOUND_renderer[wod]) { 1369 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) { 1370 device = DSOUND_renderer[wod]; 1371 DirectSoundDevice_AddRef(device); 1372 *ppDevice = device; 1373 return DS_OK; 1374 } else { 1375 ERR("device GUID doesn't match\n"); 1376 hr = DSERR_GENERIC; 1377 return hr; 1378 } 1379 } else { 1380 hr = DirectSoundDevice_Create(&device); 1381 if (hr != DS_OK) { 1382 WARN("DirectSoundDevice_Create failed\n"); 1383 return hr; 1384 } 1385 } 1386 1387 *ppDevice = device; 1388 device->guid = devGUID; 1389 device->driver = NULL; 1390 1391 device->drvdesc.dnDevNode = wod; 1392 hr = DSOUND_ReopenDevice(device, FALSE); 1393 if (FAILED(hr)) 1394 { 1395 WARN("DSOUND_ReopenDevice failed: %08x\n", hr); 1396 return hr; 1397 } 1398 1399 if (device->driver) { 1400 /* the driver is now open, so it's now allowed to call GetCaps */ 1401 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps)); 1402 if (hr != DS_OK) { 1403 WARN("IDsDriver_GetCaps failed\n"); 1404 return hr; 1405 } 1406 } else { 1407 WAVEOUTCAPSA woc; 1408 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc))); 1409 if (hr != DS_OK) { 1410 WARN("waveOutGetDevCaps failed\n"); 1411 return hr; 1412 } 1413 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps)); 1414 if ((woc.dwFormats & WAVE_FORMAT_1M08) || 1415 (woc.dwFormats & WAVE_FORMAT_2M08) || 1416 (woc.dwFormats & WAVE_FORMAT_4M08) || 1417 (woc.dwFormats & WAVE_FORMAT_48M08) || 1418 (woc.dwFormats & WAVE_FORMAT_96M08)) { 1419 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; 1420 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; 1421 } 1422 if ((woc.dwFormats & WAVE_FORMAT_1M16) || 1423 (woc.dwFormats & WAVE_FORMAT_2M16) || 1424 (woc.dwFormats & WAVE_FORMAT_4M16) || 1425 (woc.dwFormats & WAVE_FORMAT_48M16) || 1426 (woc.dwFormats & WAVE_FORMAT_96M16)) { 1427 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; 1428 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; 1429 } 1430 if ((woc.dwFormats & WAVE_FORMAT_1S08) || 1431 (woc.dwFormats & WAVE_FORMAT_2S08) || 1432 (woc.dwFormats & WAVE_FORMAT_4S08) || 1433 (woc.dwFormats & WAVE_FORMAT_48S08) || 1434 (woc.dwFormats & WAVE_FORMAT_96S08)) { 1435 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; 1436 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; 1437 } 1438 if ((woc.dwFormats & WAVE_FORMAT_1S16) || 1439 (woc.dwFormats & WAVE_FORMAT_2S16) || 1440 (woc.dwFormats & WAVE_FORMAT_4S16) || 1441 (woc.dwFormats & WAVE_FORMAT_48S16) || 1442 (woc.dwFormats & WAVE_FORMAT_96S16)) { 1443 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; 1444 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; 1445 } 1446 if (ds_emuldriver) 1447 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; 1448 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; 1449 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; 1450 ZeroMemory(&device->volpan, sizeof(device->volpan)); 1451 } 1452 1453 hr = DSOUND_PrimaryCreate(device); 1454 if (hr == DS_OK) { 1455 UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id; 1456 TIMECAPS time; 1457 1458 DSOUND_renderer[device->drvdesc.dnDevNode] = device; 1459 timeGetDevCaps(&time, sizeof(TIMECAPS)); 1460 TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax); 1461 if (triggertime < time.wPeriodMin) 1462 triggertime = time.wPeriodMin; 1463 if (res < time.wPeriodMin) 1464 res = time.wPeriodMin; 1465 if (timeBeginPeriod(res) == TIMERR_NOCANDO) 1466 WARN("Could not set minimum resolution, don't expect sound\n"); 1467 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS); 1468 if (!id) 1469 { 1470 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n"); 1471 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC); 1472 if (!id) ERR("Could not create timer, sound playback will not occur\n"); 1473 } 1474 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id; 1475 } else { 1476 WARN("DSOUND_PrimaryCreate failed\n"); 1477 } 1478 1479 return hr; 1480 } 1481 1482 HRESULT DirectSoundDevice_CreateSoundBuffer( 1483 DirectSoundDevice * device, 1484 LPCDSBUFFERDESC dsbd, 1485 LPLPDIRECTSOUNDBUFFER ppdsb, 1486 LPUNKNOWN lpunk, 1487 BOOL from8) 1488 { 1489 HRESULT hres = DS_OK; 1490 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk); 1491 1492 if (device == NULL) { 1493 WARN("not initialized\n"); 1494 return DSERR_UNINITIALIZED; 1495 } 1496 1497 if (dsbd == NULL) { 1498 WARN("invalid parameter: dsbd == NULL\n"); 1499 return DSERR_INVALIDPARAM; 1500 } 1501 1502 if (dsbd->dwSize != sizeof(DSBUFFERDESC) && 1503 dsbd->dwSize != sizeof(DSBUFFERDESC1)) { 1504 WARN("invalid parameter: dsbd\n"); 1505 return DSERR_INVALIDPARAM; 1506 } 1507 1508 if (ppdsb == NULL) { 1509 WARN("invalid parameter: ppdsb == NULL\n"); 1510 return DSERR_INVALIDPARAM; 1511 } 1512 *ppdsb = NULL; 1513 1514 if (TRACE_ON(dsound)) { 1515 TRACE("(structsize=%d)\n",dsbd->dwSize); 1516 TRACE("(flags=0x%08x:\n",dsbd->dwFlags); 1517 _dump_DSBCAPS(dsbd->dwFlags); 1518 TRACE(")\n"); 1519 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes); 1520 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat); 1521 } 1522 1523 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) { 1524 if (dsbd->lpwfxFormat != NULL) { 1525 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for " 1526 "primary buffer\n"); 1527 return DSERR_INVALIDPARAM; 1528 } 1529 1530 if (device->primary) { 1531 WARN("Primary Buffer already created\n"); 1532 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary)); 1533 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary); 1534 } else { 1535 hres = primarybuffer_create(device, &device->primary, dsbd); 1536 if (device->primary) { 1537 *ppdsb = (IDirectSoundBuffer*)&device->primary->IDirectSoundBuffer8_iface; 1538 device->primary->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE); 1539 if (device->hwbuf) 1540 device->primary->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE; 1541 else 1542 device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE; 1543 } else 1544 WARN("primarybuffer_create() failed\n"); 1545 } 1546 } else { 1547 IDirectSoundBufferImpl * dsb; 1548 WAVEFORMATEXTENSIBLE *pwfxe; 1549 1550 if (dsbd->lpwfxFormat == NULL) { 1551 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for " 1552 "secondary buffer\n"); 1553 return DSERR_INVALIDPARAM; 1554 } 1555 pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat; 1556 1557 if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) 1558 { 1559 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample); 1560 return DSERR_CONTROLUNAVAIL; 1561 } 1562 if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) 1563 { 1564 /* check if cbSize is at least 22 bytes */ 1565 if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))) 1566 { 1567 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize); 1568 return DSERR_INVALIDPARAM; 1569 } 1570 1571 /* cbSize should be 22 bytes, with one possible exception */ 1572 if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) && 1573 !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) && 1574 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE))) 1575 { 1576 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize); 1577 return DSERR_CONTROLUNAVAIL; 1578 } 1579 1580 if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))) 1581 { 1582 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL)) 1583 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat)); 1584 return DSERR_INVALIDPARAM; 1585 } 1586 if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample) 1587 { 1588 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample); 1589 return DSERR_INVALIDPARAM; 1590 } 1591 if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample) 1592 { 1593 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample); 1594 return DSERR_CONTROLUNAVAIL; 1595 } 1596 } 1597 1598 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," 1599 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", 1600 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels, 1601 dsbd->lpwfxFormat->nSamplesPerSec, 1602 dsbd->lpwfxFormat->nAvgBytesPerSec, 1603 dsbd->lpwfxFormat->nBlockAlign, 1604 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize); 1605 1606 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) { 1607 WARN("invalid parameter: 3D buffer format must be mono\n"); 1608 return DSERR_INVALIDPARAM; 1609 } 1610 1611 hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd); 1612 if (dsb) 1613 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface; 1614 else 1615 WARN("IDirectSoundBufferImpl_Create failed\n"); 1616 } 1617 1618 return hres; 1619 } 1620 1621 HRESULT DirectSoundDevice_DuplicateSoundBuffer( 1622 DirectSoundDevice * device, 1623 LPDIRECTSOUNDBUFFER psb, 1624 LPLPDIRECTSOUNDBUFFER ppdsb) 1625 { 1626 HRESULT hres = DS_OK; 1627 IDirectSoundBufferImpl* dsb; 1628 TRACE("(%p,%p,%p)\n",device,psb,ppdsb); 1629 1630 if (device == NULL) { 1631 WARN("not initialized\n"); 1632 return DSERR_UNINITIALIZED; 1633 } 1634 1635 if (psb == NULL) { 1636 WARN("invalid parameter: psb == NULL\n"); 1637 return DSERR_INVALIDPARAM; 1638 } 1639 1640 if (ppdsb == NULL) { 1641 WARN("invalid parameter: ppdsb == NULL\n"); 1642 return DSERR_INVALIDPARAM; 1643 } 1644 1645 /* make sure we have a secondary buffer */ 1646 if (psb == (IDirectSoundBuffer *)&device->primary->IDirectSoundBuffer8_iface) { 1647 WARN("trying to duplicate primary buffer\n"); 1648 *ppdsb = NULL; 1649 return DSERR_INVALIDCALL; 1650 } 1651 1652 /* duplicate the actual buffer implementation */ 1653 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb, (IDirectSoundBufferImpl*)psb); 1654 if (hres == DS_OK) 1655 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface; 1656 else 1657 WARN("IDirectSoundBufferImpl_Duplicate failed\n"); 1658 1659 return hres; 1660 } 1661 1662 HRESULT DirectSoundDevice_SetCooperativeLevel( 1663 DirectSoundDevice * device, 1664 HWND hwnd, 1665 DWORD level) 1666 { 1667 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level)); 1668 1669 if (device == NULL) { 1670 WARN("not initialized\n"); 1671 return DSERR_UNINITIALIZED; 1672 } 1673 1674 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) { 1675 WARN("level=%s not fully supported\n", 1676 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); 1677 } 1678 1679 device->priolevel = level; 1680 return DS_OK; 1681 } 1682 1683 HRESULT DirectSoundDevice_Compact( 1684 DirectSoundDevice * device) 1685 { 1686 TRACE("(%p)\n", device); 1687 1688 if (device == NULL) { 1689 WARN("not initialized\n"); 1690 return DSERR_UNINITIALIZED; 1691 } 1692 1693 if (device->priolevel < DSSCL_PRIORITY) { 1694 WARN("incorrect priority level\n"); 1695 return DSERR_PRIOLEVELNEEDED; 1696 } 1697 1698 return DS_OK; 1699 } 1700 1701 HRESULT DirectSoundDevice_GetSpeakerConfig( 1702 DirectSoundDevice * device, 1703 LPDWORD lpdwSpeakerConfig) 1704 { 1705 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig); 1706 1707 if (device == NULL) { 1708 WARN("not initialized\n"); 1709 return DSERR_UNINITIALIZED; 1710 } 1711 1712 if (lpdwSpeakerConfig == NULL) { 1713 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n"); 1714 return DSERR_INVALIDPARAM; 1715 } 1716 1717 WARN("not fully functional\n"); 1718 *lpdwSpeakerConfig = device->speaker_config; 1719 return DS_OK; 1720 } 1721 1722 HRESULT DirectSoundDevice_SetSpeakerConfig( 1723 DirectSoundDevice * device, 1724 DWORD config) 1725 { 1726 TRACE("(%p,0x%08x)\n",device,config); 1727 1728 if (device == NULL) { 1729 WARN("not initialized\n"); 1730 return DSERR_UNINITIALIZED; 1731 } 1732 1733 device->speaker_config = config; 1734 WARN("not fully functional\n"); 1735 return DS_OK; 1736 } 1737 1738 HRESULT DirectSoundDevice_VerifyCertification( 1739 DirectSoundDevice * device, 1740 LPDWORD pdwCertified) 1741 { 1742 TRACE("(%p, %p)\n",device,pdwCertified); 1743 1744 if (device == NULL) { 1745 WARN("not initialized\n"); 1746 return DSERR_UNINITIALIZED; 1747 } 1748 1749 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED) 1750 *pdwCertified = DS_CERTIFIED; 1751 else 1752 *pdwCertified = DS_UNCERTIFIED; 1753 1754 return DS_OK; 1755 } 1756 1757 /* 1758 * Add secondary buffer to buffer list. 1759 * Gets exclusive access to buffer for writing. 1760 */ 1761 HRESULT DirectSoundDevice_AddBuffer( 1762 DirectSoundDevice * device, 1763 IDirectSoundBufferImpl * pDSB) 1764 { 1765 IDirectSoundBufferImpl **newbuffers; 1766 HRESULT hr = DS_OK; 1767 1768 TRACE("(%p, %p)\n", device, pDSB); 1769 1770 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); 1771 1772 if (device->buffers) 1773 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1)); 1774 else 1775 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1)); 1776 1777 if (newbuffers) { 1778 device->buffers = newbuffers; 1779 device->buffers[device->nrofbuffers] = pDSB; 1780 device->nrofbuffers++; 1781 TRACE("buffer count is now %d\n", device->nrofbuffers); 1782 } else { 1783 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers); 1784 hr = DSERR_OUTOFMEMORY; 1785 } 1786 1787 RtlReleaseResource(&(device->buffer_list_lock)); 1788 1789 return hr; 1790 } 1791 1792 /* 1793 * Remove secondary buffer from buffer list. 1794 * Gets exclusive access to buffer for writing. 1795 */ 1796 HRESULT DirectSoundDevice_RemoveBuffer( 1797 DirectSoundDevice * device, 1798 IDirectSoundBufferImpl * pDSB) 1799 { 1800 int i; 1801 HRESULT hr = DS_OK; 1802 1803 TRACE("(%p, %p)\n", device, pDSB); 1804 1805 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); 1806 1807 for (i = 0; i < device->nrofbuffers; i++) 1808 if (device->buffers[i] == pDSB) 1809 break; 1810 1811 if (i < device->nrofbuffers) { 1812 /* Put the last buffer of the list in the (now empty) position */ 1813 device->buffers[i] = device->buffers[device->nrofbuffers - 1]; 1814 device->nrofbuffers--; 1815 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers); 1816 TRACE("buffer count is now %d\n", device->nrofbuffers); 1817 } 1818 1819 if (device->nrofbuffers == 0) { 1820 HeapFree(GetProcessHeap(),0,device->buffers); 1821 device->buffers = NULL; 1822 } 1823 1824 RtlReleaseResource(&(device->buffer_list_lock)); 1825 1826 return hr; 1827 } 1828