1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Configuration of network devices 4 * FILE: dll/directx/dsound_new/primary.c 5 * PURPOSE: Primary IDirectSoundBuffer8 implementation 6 * 7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 10 11 #include "precomp.h" 12 13 typedef struct 14 { 15 const IDirectSoundBuffer8Vtbl *lpVtbl; 16 LONG ref; 17 18 LPFILTERINFO Filter; 19 DWORD dwLevel; 20 DWORD dwFlags; 21 DWORD dwFrequency; 22 LONG Volume; 23 LONG VolumePan; 24 WAVEFORMATEX Format; 25 HANDLE hPin; 26 CRITICAL_SECTION Lock; 27 KSSTATE State; 28 }CDirectSoundBuffer, *LPCDirectSoundBuffer; 29 30 HRESULT 31 WINAPI 32 PrimaryDirectSoundBuffer8Impl_fnQueryInterface( 33 LPDIRECTSOUNDBUFFER8 iface, 34 IN REFIID riid, 35 LPVOID* ppobj) 36 { 37 LPOLESTR pStr; 38 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 39 40 if (IsEqualIID(riid, &IID_IUnknown) || 41 IsEqualIID(riid, &IID_IDirectSoundBuffer) || 42 IsEqualIID(riid, &IID_IDirectSoundBuffer8)) 43 { 44 *ppobj = (LPVOID)&This->lpVtbl; 45 InterlockedIncrement(&This->ref); 46 return S_OK; 47 } 48 49 if (SUCCEEDED(StringFromIID(riid, &pStr))) 50 { 51 DPRINT("No Interface for class %s\n", pStr); 52 CoTaskMemFree(pStr); 53 } 54 return E_NOINTERFACE; 55 } 56 57 ULONG 58 WINAPI 59 PrimaryDirectSoundBuffer8Impl_fnAddRef( 60 LPDIRECTSOUNDBUFFER8 iface) 61 { 62 ULONG ref; 63 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 64 65 ref = InterlockedIncrement(&This->ref); 66 67 return ref; 68 69 } 70 71 ULONG 72 WINAPI 73 PrimaryDirectSoundBuffer8Impl_fnRelease( 74 LPDIRECTSOUNDBUFFER8 iface) 75 { 76 ULONG ref; 77 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 78 79 ref = InterlockedDecrement(&(This->ref)); 80 81 if (!ref) 82 { 83 if (This->hPin) 84 { 85 /* close pin handle */ 86 CloseHandle(This->hPin); 87 } 88 /* free primary buffer */ 89 HeapFree(GetProcessHeap(), 0, This); 90 } 91 92 return ref; 93 } 94 95 HRESULT 96 WINAPI 97 PrimaryDirectSoundBuffer8Impl_fnGetCaps( 98 LPDIRECTSOUNDBUFFER8 iface, 99 LPDSBCAPS pDSBufferCaps) 100 { 101 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 102 103 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetCaps\n"); 104 105 if (!pDSBufferCaps) 106 { 107 /* invalid parameter */ 108 return DSERR_INVALIDPARAM; 109 } 110 111 if (pDSBufferCaps->dwSize < sizeof(DSBCAPS)) 112 { 113 /* invalid buffer size */ 114 return DSERR_INVALIDPARAM; 115 } 116 117 /* get buffer details */ 118 pDSBufferCaps->dwUnlockTransferRate = 0; 119 pDSBufferCaps->dwPlayCpuOverhead = 0; 120 pDSBufferCaps->dwSize = 0; //FIXME 121 pDSBufferCaps->dwFlags = This->dwFlags; 122 123 return DS_OK; 124 } 125 126 HRESULT 127 WINAPI 128 PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition( 129 LPDIRECTSOUNDBUFFER8 iface, 130 LPDWORD pdwCurrentPlayCursor, 131 LPDWORD pdwCurrentWriteCursor) 132 { 133 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 134 135 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition\n"); 136 137 if (This->dwLevel < DSSCL_PRIORITY) 138 { 139 /* needs priority level */ 140 return DSERR_PRIOLEVELNEEDED; 141 } 142 143 if (!pdwCurrentPlayCursor && !pdwCurrentWriteCursor) 144 { 145 /* all parameters are null */ 146 return DSERR_INVALIDPARAM; 147 } 148 149 UNIMPLEMENTED; 150 return DSERR_INVALIDPARAM; 151 } 152 153 HRESULT 154 WINAPI 155 PrimaryDirectSoundBuffer8Impl_fnGetFormat( 156 LPDIRECTSOUNDBUFFER8 iface, 157 LPWAVEFORMATEX pwfxFormat, 158 DWORD dwSizeAllocated, 159 LPDWORD pdwSizeWritten) 160 { 161 DWORD FormatSize; 162 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 163 164 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetFormat\n"); 165 166 FormatSize = sizeof(WAVEFORMATEX) + This->Format.cbSize; 167 168 if (!pwfxFormat && !pdwSizeWritten) 169 { 170 /* invalid parameter */ 171 return DSERR_INVALIDPARAM; 172 } 173 174 if (!pwfxFormat) 175 { 176 /* return required format size */ 177 *pdwSizeWritten = FormatSize; 178 return DS_OK; 179 } 180 else 181 { 182 if (dwSizeAllocated >= FormatSize) 183 { 184 /* copy format */ 185 CopyMemory(pwfxFormat, &This->Format, FormatSize); 186 187 if (pdwSizeWritten) 188 *pdwSizeWritten = FormatSize; 189 190 return DS_OK; 191 } 192 /* buffer too small */ 193 if (pdwSizeWritten) 194 *pdwSizeWritten = 0; 195 196 return DSERR_INVALIDPARAM; 197 } 198 } 199 200 HRESULT 201 WINAPI 202 PrimaryDirectSoundBuffer8Impl_fnGetVolume( 203 LPDIRECTSOUNDBUFFER8 iface, 204 LPLONG plVolume) 205 { 206 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 207 208 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetVolume\n"); 209 210 if (!plVolume) 211 { 212 /* invalid parameter */ 213 return DSERR_INVALIDPARAM; 214 } 215 216 /* get volume */ 217 *plVolume = This->Volume; 218 219 return DS_OK; 220 } 221 222 HRESULT 223 WINAPI 224 PrimaryDirectSoundBuffer8Impl_fnGetPan( 225 LPDIRECTSOUNDBUFFER8 iface, 226 LPLONG plPan) 227 { 228 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 229 230 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetPan\n"); 231 232 if (!plPan) 233 { 234 /* invalid parameter */ 235 return DSERR_INVALIDPARAM; 236 } 237 238 /* get frequency */ 239 *plPan = This->VolumePan; 240 241 return DS_OK; 242 } 243 244 HRESULT 245 WINAPI 246 PrimaryDirectSoundBuffer8Impl_fnGetFrequency( 247 LPDIRECTSOUNDBUFFER8 iface, 248 LPDWORD pdwFrequency) 249 { 250 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 251 252 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetFrequency\n"); 253 254 if (!pdwFrequency) 255 { 256 /* invalid parameter */ 257 return DSERR_INVALIDPARAM; 258 } 259 260 /* get frequency */ 261 *pdwFrequency = This->dwFrequency; 262 263 return DS_OK; 264 } 265 266 HRESULT 267 WINAPI 268 PrimaryDirectSoundBuffer8Impl_fnGetStatus( 269 LPDIRECTSOUNDBUFFER8 iface, 270 LPDWORD pdwStatus) 271 { 272 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 273 274 DPRINT("PrimaryDirectSoundBuffer8Impl_fnGetStatus\n"); 275 276 if (!pdwStatus) 277 { 278 /* invalid parameter */ 279 return DSERR_INVALIDPARAM; 280 } 281 282 *pdwStatus = 0; 283 if (This->State == KSSTATE_RUN || This->State == KSSTATE_ACQUIRE) 284 { 285 /* buffer is playing */ 286 *pdwStatus |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING; 287 } 288 289 return DS_OK; 290 } 291 292 HRESULT 293 WINAPI 294 PrimaryDirectSoundBuffer8Impl_fnInitialize( 295 LPDIRECTSOUNDBUFFER8 iface, 296 LPDIRECTSOUND pDirectSound, 297 LPCDSBUFFERDESC pcDSBufferDesc) 298 { 299 /* RTFM */ 300 return DSERR_ALREADYINITIALIZED; 301 } 302 303 HRESULT 304 WINAPI 305 PrimaryDirectSoundBuffer8Impl_fnLock( 306 LPDIRECTSOUNDBUFFER8 iface, 307 DWORD dwOffset, 308 DWORD dwBytes, 309 LPVOID *ppvAudioPtr1, 310 LPDWORD pdwAudioBytes1, 311 LPVOID *ppvAudioPtr2, 312 LPDWORD pdwAudioBytes2, 313 DWORD dwFlags) 314 { 315 UNIMPLEMENTED; 316 return DSERR_INVALIDPARAM; 317 } 318 319 HRESULT 320 WINAPI 321 PrimaryDirectSoundBuffer8Impl_fnPlay( 322 LPDIRECTSOUNDBUFFER8 iface, 323 DWORD dwReserved1, 324 DWORD dwPriority, 325 DWORD dwFlags) 326 { 327 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 328 329 DPRINT("PrimaryDirectSoundBuffer8Impl_fnPlay dwFlags %x\n", dwFlags); 330 331 if (dwReserved1 != 0 || !(dwFlags & DSBPLAY_LOOPING)) 332 { 333 /* invalid parameter */ 334 return DSERR_INVALIDPARAM; 335 } 336 337 PrimaryDirectSoundBuffer_AcquireLock(iface); 338 339 if (This->State == KSSTATE_STOP) 340 { 341 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_ACQUIRE); 342 ASSERT(This->State == KSSTATE_ACQUIRE); 343 } 344 345 if (This->State == KSSTATE_ACQUIRE) 346 { 347 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_PAUSE); 348 ASSERT(This->State == KSSTATE_PAUSE); 349 } 350 351 if (This->State == KSSTATE_PAUSE) 352 { 353 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_RUN); 354 ASSERT(This->State == KSSTATE_RUN); 355 } 356 357 PrimaryDirectSoundBuffer_ReleaseLock(iface); 358 359 return DS_OK; 360 } 361 362 HRESULT 363 WINAPI 364 PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition( 365 LPDIRECTSOUNDBUFFER8 iface, 366 DWORD dwNewPosition) 367 { 368 /* The position of a primary buffer can't be set */ 369 return DSERR_INVALIDCALL; 370 } 371 372 HRESULT 373 WINAPI 374 PrimaryDirectSoundBuffer8Impl_fnSetFormat( 375 LPDIRECTSOUNDBUFFER8 iface, 376 LPCWAVEFORMATEX pcfxFormat) 377 { 378 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 379 380 if (This->dwLevel == DSSCL_NORMAL) 381 { 382 /* can't change format with this level */ 383 return DSERR_PRIOLEVELNEEDED; 384 } 385 386 ASSERT(pcfxFormat->cbSize == 0); 387 388 389 DPRINT("This %p Format: Tag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u nBlockAlign %u wBitsPerSample %u cbSize %u\n", This, 390 pcfxFormat->wFormatTag, pcfxFormat->nChannels, pcfxFormat->nSamplesPerSec, pcfxFormat->nAvgBytesPerSec, pcfxFormat->nBlockAlign, pcfxFormat->wBitsPerSample, pcfxFormat->cbSize); 391 392 CopyMemory(&This->Format, pcfxFormat, sizeof(WAVEFORMATEX)); 393 394 return DS_OK; 395 } 396 397 HRESULT 398 WINAPI 399 PrimaryDirectSoundBuffer8Impl_fnSetVolume( 400 LPDIRECTSOUNDBUFFER8 iface, 401 LONG lVolume) 402 { 403 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 404 405 if (lVolume < DSBVOLUME_MIN || lVolume > DSBVOLUME_MAX) 406 { 407 /* invalid parameter */ 408 return DSERR_INVALIDPARAM; 409 } 410 411 /* TODO: call volume node */ 412 413 /* Store volume */ 414 This->Volume = lVolume; 415 416 return DS_OK; 417 } 418 419 HRESULT 420 WINAPI 421 PrimaryDirectSoundBuffer8Impl_fnSetPan( 422 LPDIRECTSOUNDBUFFER8 iface, 423 LONG lPan) 424 { 425 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 426 427 if (lPan < DSBPAN_LEFT || lPan > DSBPAN_RIGHT) 428 { 429 /* invalid parameter */ 430 return DSERR_INVALIDPARAM; 431 } 432 433 /* TODO: call volume node */ 434 435 /* Store volume pan */ 436 This->VolumePan = lPan; 437 438 return DS_OK; 439 } 440 441 HRESULT 442 WINAPI 443 PrimaryDirectSoundBuffer8Impl_fnSetFrequency( 444 LPDIRECTSOUNDBUFFER8 iface, 445 DWORD dwFrequency) 446 { 447 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 448 449 if (This->dwLevel < DSSCL_PRIORITY) 450 { 451 /* needs priority level */ 452 return DSERR_PRIOLEVELNEEDED; 453 } 454 455 /* invalid request */ 456 return DSERR_CONTROLUNAVAIL; 457 } 458 459 HRESULT 460 WINAPI 461 PrimaryDirectSoundBuffer8Impl_fnStop( 462 LPDIRECTSOUNDBUFFER8 iface) 463 { 464 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 465 466 DPRINT("PrimaryDirectSoundBuffer8Impl_fnStop\n"); 467 468 PrimaryDirectSoundBuffer_AcquireLock(iface); 469 470 if (This->State == KSSTATE_RUN) 471 { 472 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_PAUSE); 473 ASSERT(This->State == KSSTATE_PAUSE); 474 } 475 476 if (This->State == KSSTATE_PAUSE) 477 { 478 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_ACQUIRE); 479 ASSERT(This->State == KSSTATE_ACQUIRE); 480 } 481 482 if (This->State == KSSTATE_ACQUIRE) 483 { 484 PrimaryDirectSoundBuffer_SetState(iface, KSSTATE_STOP); 485 ASSERT(This->State == KSSTATE_STOP); 486 } 487 488 PrimaryDirectSoundBuffer_ReleaseLock(iface); 489 490 return DS_OK; 491 } 492 493 494 HRESULT 495 WINAPI 496 PrimaryDirectSoundBuffer8Impl_fnUnlock( 497 LPDIRECTSOUNDBUFFER8 iface, 498 LPVOID pvAudioPtr1, 499 DWORD dwAudioBytes1, 500 LPVOID pvAudioPtr2, 501 DWORD dwAudioBytes2) 502 { 503 UNIMPLEMENTED; 504 return DSERR_INVALIDPARAM; 505 } 506 507 508 HRESULT 509 WINAPI 510 PrimaryDirectSoundBuffer8Impl_fnRestore( 511 LPDIRECTSOUNDBUFFER8 iface) 512 { 513 UNIMPLEMENTED; 514 return DSERR_INVALIDPARAM; 515 } 516 517 518 HRESULT 519 WINAPI 520 PrimaryDirectSoundBuffer8Impl_fnSetFX( 521 LPDIRECTSOUNDBUFFER8 iface, 522 DWORD dwEffectsCount, 523 LPDSEFFECTDESC pDSFXDesc, 524 LPDWORD pdwResultCodes) 525 { 526 UNIMPLEMENTED; 527 return DSERR_INVALIDPARAM; 528 } 529 530 HRESULT 531 WINAPI 532 PrimaryDirectSoundBuffer8Impl_fnAcquireResources( 533 LPDIRECTSOUNDBUFFER8 iface, 534 DWORD dwFlags, 535 DWORD dwEffectsCount, 536 LPDWORD pdwResultCodes) 537 { 538 UNIMPLEMENTED; 539 return DSERR_INVALIDPARAM; 540 } 541 542 HRESULT 543 WINAPI 544 PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath( 545 LPDIRECTSOUNDBUFFER8 iface, 546 REFGUID rguidObject, 547 DWORD dwIndex, 548 REFGUID rguidInterface, 549 LPVOID *ppObject) 550 { 551 UNIMPLEMENTED; 552 return DSERR_INVALIDPARAM; 553 } 554 555 static IDirectSoundBuffer8Vtbl vt_DirectSoundBuffer8 = 556 { 557 /* IUnknown methods */ 558 PrimaryDirectSoundBuffer8Impl_fnQueryInterface, 559 PrimaryDirectSoundBuffer8Impl_fnAddRef, 560 PrimaryDirectSoundBuffer8Impl_fnRelease, 561 /* IDirectSoundBuffer methods */ 562 PrimaryDirectSoundBuffer8Impl_fnGetCaps, 563 PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition, 564 PrimaryDirectSoundBuffer8Impl_fnGetFormat, 565 PrimaryDirectSoundBuffer8Impl_fnGetVolume, 566 PrimaryDirectSoundBuffer8Impl_fnGetPan, 567 PrimaryDirectSoundBuffer8Impl_fnGetFrequency, 568 PrimaryDirectSoundBuffer8Impl_fnGetStatus, 569 PrimaryDirectSoundBuffer8Impl_fnInitialize, 570 PrimaryDirectSoundBuffer8Impl_fnLock, 571 PrimaryDirectSoundBuffer8Impl_fnPlay, 572 PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition, 573 PrimaryDirectSoundBuffer8Impl_fnSetFormat, 574 PrimaryDirectSoundBuffer8Impl_fnSetVolume, 575 PrimaryDirectSoundBuffer8Impl_fnSetPan, 576 PrimaryDirectSoundBuffer8Impl_fnSetFrequency, 577 PrimaryDirectSoundBuffer8Impl_fnStop, 578 PrimaryDirectSoundBuffer8Impl_fnUnlock, 579 PrimaryDirectSoundBuffer8Impl_fnRestore, 580 /* IDirectSoundBuffer8 methods */ 581 PrimaryDirectSoundBuffer8Impl_fnSetFX, 582 PrimaryDirectSoundBuffer8Impl_fnAcquireResources, 583 PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath 584 }; 585 586 DWORD 587 PrimaryDirectSoundBuffer_Write( 588 LPDIRECTSOUNDBUFFER8 iface, 589 LPVOID Buffer, 590 DWORD BufferSize) 591 { 592 KSSTREAM_HEADER Header; 593 DWORD Result, BytesTransferred; 594 OVERLAPPED Overlapped; 595 596 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 597 598 ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); 599 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 600 601 602 ASSERT(This->hPin); 603 ZeroMemory(&Header, sizeof(KSSTREAM_HEADER)); 604 605 Header.FrameExtent = BufferSize; 606 Header.DataUsed = BufferSize; 607 Header.Data = Buffer; 608 Header.Size = sizeof(KSSTREAM_HEADER); 609 Header.PresentationTime.Numerator = 1; 610 Header.PresentationTime.Denominator = 1; 611 612 Result = DeviceIoControl(This->hPin, IOCTL_KS_WRITE_STREAM, NULL, 0, &Header, sizeof(KSSTREAM_HEADER), &BytesTransferred, &Overlapped); 613 614 if (Result != ERROR_SUCCESS) 615 return 0; 616 617 return BytesTransferred; 618 } 619 620 VOID 621 PrimaryDirectSoundBuffer_SetState( 622 LPDIRECTSOUNDBUFFER8 iface, 623 KSSTATE State) 624 { 625 KSPROPERTY Property; 626 DWORD Result, BytesTransferred; 627 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 628 629 if (This->State == State) 630 return; 631 632 Property.Set = KSPROPSETID_Connection; 633 Property.Id = KSPROPERTY_CONNECTION_STATE; 634 Property.Flags = KSPROPERTY_TYPE_SET; 635 636 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesTransferred); 637 if (Result == ERROR_SUCCESS) 638 { 639 This->State = State; 640 } 641 } 642 643 HRESULT 644 PrimaryDirectSoundBuffer_GetPosition( 645 LPDIRECTSOUNDBUFFER8 iface, 646 LPDWORD pdwCurrentPlayCursor, 647 LPDWORD pdwCurrentWriteCursor) 648 { 649 KSAUDIO_POSITION Position; 650 KSPROPERTY Request; 651 DWORD Result; 652 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 653 654 //DPRINT("PrimaryDirectSoundBuffer_GetPosition\n"); 655 656 if (!This->hPin) 657 { 658 if (pdwCurrentPlayCursor) 659 *pdwCurrentPlayCursor = 0; 660 661 if (pdwCurrentWriteCursor) 662 *pdwCurrentWriteCursor = 0; 663 664 DPRINT("No Audio Pin\n"); 665 return DS_OK; 666 } 667 668 /* setup audio position property request */ 669 Request.Id = KSPROPERTY_AUDIO_POSITION; 670 Request.Set = KSPROPSETID_Audio; 671 Request.Flags = KSPROPERTY_TYPE_GET; 672 673 674 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL); 675 676 if (Result != ERROR_SUCCESS) 677 { 678 DPRINT("GetPosition failed with %x\n", Result); 679 return DSERR_UNSUPPORTED; 680 } 681 682 //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset); 683 684 if (pdwCurrentPlayCursor) 685 *pdwCurrentPlayCursor = (DWORD)Position.PlayOffset; 686 687 if (pdwCurrentWriteCursor) 688 *pdwCurrentWriteCursor = (DWORD)Position.WriteOffset; 689 690 return DS_OK; 691 } 692 693 HRESULT 694 PrimaryDirectSoundBuffer_SetFormat( 695 LPDIRECTSOUNDBUFFER8 iface, 696 LPWAVEFORMATEX pcfxFormat, 697 BOOL bLooped) 698 { 699 ULONG PinId, DeviceId = 0, Result; 700 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 701 702 if (This->hPin) 703 { 704 // FIXME 705 // check if multiple buffers are active 706 // in that case need mixing 707 708 if (SetPinFormat(This->hPin, pcfxFormat)) 709 return DS_OK; 710 else 711 return DSERR_GENERIC; 712 } 713 714 do 715 { 716 /* try all available recording pins on that filter */ 717 PinId = GetPinIdFromFilter(This->Filter, FALSE, DeviceId); 718 DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId); 719 720 if (PinId == ULONG_MAX) 721 break; 722 723 Result = OpenPin(This->Filter->hFilter, PinId, (LPWAVEFORMATEX)pcfxFormat, &This->hPin, bLooped); 724 DPRINT("PinId %u Result %u\n", PinId, Result); 725 if (Result == ERROR_SUCCESS) 726 { 727 This->dwFrequency = pcfxFormat->nSamplesPerSec; 728 break; 729 } 730 731 This->hPin = NULL; 732 DeviceId++; 733 }while(TRUE); 734 735 if (!This->hPin) 736 { 737 DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat failed\n"); 738 return DSERR_INVALIDPARAM; 739 } 740 741 DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat success\n"); 742 return DS_OK; 743 } 744 745 VOID 746 PrimaryDirectSoundBuffer_AcquireLock( 747 LPDIRECTSOUNDBUFFER8 iface) 748 { 749 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 750 751 EnterCriticalSection(&This->Lock); 752 753 754 } 755 756 VOID 757 PrimaryDirectSoundBuffer_ReleaseLock( 758 LPDIRECTSOUNDBUFFER8 iface) 759 { 760 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl); 761 762 LeaveCriticalSection(&This->Lock); 763 764 } 765 766 767 HRESULT 768 NewPrimarySoundBuffer( 769 LPDIRECTSOUNDBUFFER8 *OutBuffer, 770 LPFILTERINFO Filter, 771 DWORD dwLevel, 772 DWORD dwFlags) 773 { 774 LPCDirectSoundBuffer This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundBuffer)); 775 776 if (!This) 777 { 778 /* not enough memory */ 779 return DSERR_OUTOFMEMORY; 780 } 781 782 This->ref = 1; 783 This->lpVtbl = &vt_DirectSoundBuffer8; 784 This->Filter = Filter; 785 This->dwLevel = dwLevel; 786 This->dwFlags = dwFlags; 787 This->dwFrequency = 0; 788 This->Volume = DSBVOLUME_MAX; 789 This->VolumePan = DSBPAN_CENTER; 790 This->hPin = NULL; 791 792 /* FIXME: determine default format for audio device */ 793 This->Format.cbSize = sizeof(WAVEFORMATEX); 794 This->Format.nChannels = 2; 795 This->Format.nSamplesPerSec = 44100; 796 This->Format.wBitsPerSample = 16; 797 This->Format.wFormatTag = WAVE_FORMAT_PCM; 798 This->Format.nBlockAlign = (This->Format.nChannels * This->Format.wBitsPerSample) / 8; 799 This->Format.nAvgBytesPerSec = (This->Format.nChannels * This->Format.nSamplesPerSec * This->Format.wBitsPerSample) / 8; 800 801 InitializeCriticalSection(&This->Lock); 802 803 *OutBuffer = (LPDIRECTSOUNDBUFFER8)&This->lpVtbl; 804 return DS_OK; 805 } 806 807