Changeset 58733 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Nov 18, 2015 10:22:54 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r58378 r58733 67 67 typedef FNDIRECTSOUNDCAPTUREENUMERATEW *PFNDIRECTSOUNDCAPTUREENUMERATEW; 68 68 69 #ifdef VBOX_WITH_AUDIO_CALLBACKS 70 # define VBOX_DSOUND_MAX_EVENTS 3 71 72 typedef enum DSOUNDEVENT 73 { 74 DSOUNDEVENT_NOTIFY = 0, 75 DSOUNDEVENT_INPUT, 76 DSOUNDEVENT_OUTPUT, 77 } DSOUNDEVENT; 78 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ 79 69 80 typedef struct DSOUNDHOSTCFG 70 81 { … … 76 87 LPCGUID pGuidCapture; 77 88 } DSOUNDHOSTCFG, *PDSOUNDHOSTCFG; 89 90 typedef struct DSOUNDSTREAMOUT 91 { 92 PDMAUDIOHSTSTRMOUT strmOut; /* Always must come first! */ 93 LPDIRECTSOUND8 pDS; 94 LPDIRECTSOUNDBUFFER8 pDSB; 95 DWORD cbPlayWritePos; 96 DWORD csPlaybackBufferSize; 97 bool fRestartPlayback; 98 PDMAUDIOSTREAMCFG streamCfg; 99 } DSOUNDSTREAMOUT, *PDSOUNDSTREAMOUT; 100 101 typedef struct DSOUNDSTREAMIN 102 { 103 PDMAUDIOHSTSTRMIN strmIn; /* Always must come first! */ 104 LPDIRECTSOUNDCAPTURE8 pDSC; 105 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB; 106 DWORD csCaptureReadPos; 107 DWORD csCaptureBufferSize; 108 HRESULT hrLastCaptureIn; 109 PDMAUDIORECSOURCE enmRecSource; 110 PDMAUDIOSTREAMCFG streamCfg; 111 } DSOUNDSTREAMIN, *PDSOUNDSTREAMIN; 78 112 79 113 typedef struct DRVHOSTDSOUND … … 89 123 /** DirectSound configuration options. */ 90 124 DSOUNDHOSTCFG cfg; 125 #ifdef VBOX_WITH_AUDIO_CALLBACKS 126 /** Stopped indicator. */ 127 bool fStopped; 128 /** Shutdown indicator. */ 129 bool fShutdown; 130 /** Notification thread. */ 131 RTTHREAD Thread; 132 /** Array of events to wait for in notification thread. */ 133 HANDLE aEvents[VBOX_DSOUND_MAX_EVENTS]; 134 /** Number of events to wait for in notification thread. 135 * Must not exceed VBOX_DSOUND_MAX_EVENTS. */ 136 uint8_t cEvents; 137 PDSOUNDSTREAMIN pStrmIn; 138 PDSOUNDSTREAMOUT pStrmOut; 139 #endif 91 140 } DRVHOSTDSOUND, *PDRVHOSTDSOUND; 92 93 typedef struct DSOUNDSTREAMOUT94 {95 PDMAUDIOHSTSTRMOUT strmOut; /* Always must come first! */96 LPDIRECTSOUND8 pDS;97 LPDIRECTSOUNDBUFFER8 pDSB;98 DWORD cbPlayWritePos;99 DWORD csPlaybackBufferSize;100 bool fRestartPlayback;101 PDMAUDIOSTREAMCFG streamCfg;102 } DSOUNDSTREAMOUT, *PDSOUNDSTREAMOUT;103 104 typedef struct DSOUNDSTREAMIN105 {106 PDMAUDIOHSTSTRMIN strmIn; /* Always must come first! */107 LPDIRECTSOUNDCAPTURE8 pDSC;108 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB;109 DWORD csCaptureReadPos;110 DWORD csCaptureBufferSize;111 HRESULT hrLastCaptureIn;112 PDMAUDIORECSOURCE enmRecSource;113 PDMAUDIOSTREAMCFG streamCfg;114 } DSOUNDSTREAMIN, *PDSOUNDSTREAMIN;115 141 116 142 /** … … 135 161 136 162 static void dsoundDevRemove(PDSOUNDDEV pDev); 163 #ifdef VBOX_WITH_AUDIO_CALLBACKS 164 static int dsoundNotifyThread(PDRVHOSTDSOUND pThis, bool fShutdown); 165 #endif 137 166 138 167 static DWORD dsoundRingDistance(DWORD offEnd, DWORD offBegin, DWORD cSize) … … 376 405 } 377 406 378 static void directSoundPlayClose(PDSOUNDSTREAMOUT pDSoundStrmOut) 379 { 407 static void directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut) 408 { 409 AssertPtrReturnVoid(pThis); 410 AssertPtrReturnVoid(pDSoundStrmOut); 411 380 412 DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pDSoundStrmOut, pDSoundStrmOut->pDSB)); 381 413 … … 386 418 DSLOGREL(("DSound: Stop playback stream %p when closing %Rhrc\n", pDSoundStrmOut, hr)); 387 419 420 #ifdef VBOX_WITH_AUDIO_CALLBACKS 421 if (pThis->aEvents[DSOUNDEVENT_OUTPUT] != NULL) 422 { 423 CloseHandle(pThis->aEvents[DSOUNDEVENT_OUTPUT]); 424 pThis->aEvents[DSOUNDEVENT_OUTPUT] = NULL; 425 426 if (pThis->cEvents) 427 pThis->cEvents--; 428 429 pThis->pStrmOut = NULL; 430 } 431 #endif 388 432 IDirectSoundBuffer8_Release(pDSoundStrmOut->pDSB); 389 433 pDSoundStrmOut->pDSB = NULL; … … 410 454 /* Should not happen but be forgiving. */ 411 455 DSLOGREL(("DSound: DirectSoundBuffer already exists\n")); 412 directSoundPlayClose(p DSoundStrmOut);456 directSoundPlayClose(pThis, pDSoundStrmOut); 413 457 } 414 458 … … 425 469 { 426 470 LPDIRECTSOUNDBUFFER pDSB = NULL; 471 427 472 DSBUFFERDESC bd; 428 473 RT_ZERO(bd); 429 bd.dwSize = sizeof(bd); 430 bd.lpwfxFormat = &wfx; 431 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; 474 bd.dwSize = sizeof(bd); 475 bd.lpwfxFormat = &wfx; 476 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; 477 #ifdef VBOX_WITH_AUDIO_CALLBACKS 478 bd.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; 479 #endif 432 480 bd.dwBufferBytes = pThis->cfg.cbBufferOut; 433 hr = IDirectSound8_CreateSoundBuffer(pDSoundStrmOut->pDS, 434 481 482 hr = IDirectSound8_CreateSoundBuffer(pDSoundStrmOut->pDS, &bd, &pDSB, NULL); 435 483 if (FAILED(hr)) 436 484 { … … 439 487 } 440 488 441 /* "Upgrade" to IDirectSoundBuffer8 int arface. */442 hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, ( void **)&pDSoundStrmOut->pDSB);443 pDSB->Release();489 /* "Upgrade" to IDirectSoundBuffer8 interface. */ 490 hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (LPVOID *)&pDSoundStrmOut->pDSB); 491 IDirectSoundBuffer_Release(pDSB); 444 492 if (FAILED(hr)) 445 493 { … … 502 550 DSLOG(("DSound: csPlaybackBufferSize=%RU32\n", pDSoundStrmOut->csPlaybackBufferSize)); 503 551 552 #ifdef VBOX_WITH_AUDIO_CALLBACKS 553 /* 554 * Install notification. 555 */ 556 pThis->aEvents[DSOUNDEVENT_OUTPUT] = CreateEvent(NULL /* Security attribute */, 557 FALSE /* bManualReset */, FALSE /* bInitialState */, 558 NULL /* lpName */); 559 if (pThis->aEvents[DSOUNDEVENT_OUTPUT] == NULL) 560 { 561 hr = HRESULT_FROM_WIN32(GetLastError()); 562 DSLOGREL(("DSound: CreateEvent for output failed with hr=%Rhrc\n", hr)); 563 break; 564 } 565 566 LPDIRECTSOUNDNOTIFY8 pNotify; 567 hr = IDirectSoundNotify_QueryInterface(pDSoundStrmOut->pDSB, IID_IDirectSoundNotify8, (LPVOID *)&pNotify); 568 if (SUCCEEDED(hr)) 569 { 570 DSBPOSITIONNOTIFY dsBufPosNotify; 571 RT_ZERO(dsBufPosNotify); 572 dsBufPosNotify.dwOffset = DSBPN_OFFSETSTOP; 573 dsBufPosNotify.hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT]; 574 575 hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 1 /* Count */, &dsBufPosNotify); 576 if (FAILED(hr)) 577 DSLOGREL(("DSound: IDirectSoundNotify_SetNotificationPositions failed with hr=%Rhrc\n", hr)); 578 579 IDirectSoundNotify_Release(pNotify); 580 } 581 else 582 DSLOGREL(("DSound: IDirectSoundNotify_QueryInterface failed with hr=%Rhrc\n", hr)); 583 584 if (FAILED(hr)) 585 break; 586 587 pThis->pStrmOut = pDSoundStrmOut; 588 589 Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS); 590 pThis->cEvents++; 591 592 /* Let the thread know. */ 593 dsoundNotifyThread(pThis, false /* fShutdown */); 594 595 /* Trigger the just installed output notification. */ 596 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, 0); 597 598 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ 599 504 600 } while (0); 505 601 506 602 if (FAILED(hr)) 507 directSoundPlayClose(p DSoundStrmOut);603 directSoundPlayClose(pThis, pDSoundStrmOut); 508 604 509 605 return hr; … … 1071 1167 if (FAILED(hr)) 1072 1168 { 1073 directSoundPlayClose(p DSoundStrmOut);1169 directSoundPlayClose(pThis, pDSoundStrmOut); 1074 1170 directSoundPlayOpen(pThis, pDSoundStrmOut); 1075 1171 … … 1131 1227 hr = directSoundPlayRestore(pDSB); 1132 1228 if (SUCCEEDED(hr)) 1133 {1134 1229 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 1135 }1136 1230 } 1137 1231 … … 1241 1335 PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut; 1242 1336 1243 directSoundPlayClose(p DSoundStrmOut);1244 1245 pDSoundStrmOut->cbPlayWritePos = 0;1246 pDSoundStrmOut->fRestartPlayback = true;1337 directSoundPlayClose(pThis, pDSoundStrmOut); 1338 1339 pDSoundStrmOut->cbPlayWritePos = 0; 1340 pDSoundStrmOut->fRestartPlayback = true; 1247 1341 pDSoundStrmOut->csPlaybackBufferSize = 0; 1342 1248 1343 RT_ZERO(pDSoundStrmOut->streamCfg); 1249 1344 … … 1555 1650 } 1556 1651 1652 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1653 static int dsoundNotifyThread(PDRVHOSTDSOUND pThis, bool fShutdown) 1654 { 1655 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1656 1657 if (fShutdown) 1658 { 1659 LogFlowFunc(("Shutting down thread ...\n")); 1660 pThis->fShutdown = fShutdown; 1661 } 1662 1663 /* Set the notification event so that the thread is being notified. */ 1664 BOOL fRc = SetEvent(pThis->aEvents[DSOUNDEVENT_NOTIFY]); 1665 Assert(fRc); 1666 1667 return VINF_SUCCESS; 1668 } 1669 1670 static DECLCALLBACK(int) drvHostDSoundThread(RTTHREAD hThreadSelf, void *pvUser) 1671 { 1672 PDRVHOSTDSOUND pThis = (PDRVHOSTDSOUND)pvUser; 1673 AssertPtr(pThis); 1674 1675 LogFlowFuncEnter(); 1676 1677 /* Let caller know that we're done initializing, regardless of the result. */ 1678 int rc = RTThreadUserSignal(hThreadSelf); 1679 AssertRC(rc); 1680 1681 HRESULT hr; 1682 1683 do 1684 { 1685 HANDLE aEvents[VBOX_DSOUND_MAX_EVENTS]; 1686 DWORD cEvents = 0; 1687 for (uint8_t i = 0; i < VBOX_DSOUND_MAX_EVENTS; i++) 1688 { 1689 if (pThis->aEvents[i]) 1690 aEvents[cEvents++] = pThis->aEvents[i]; 1691 } 1692 Assert(cEvents); 1693 1694 LogFlowFunc(("Waiting: cEvents=%ld\n", cEvents)); 1695 1696 DWORD dwObj = WaitForMultipleObjects(cEvents, aEvents, FALSE /* bWaitAll */, INFINITE); 1697 switch (dwObj) 1698 { 1699 case WAIT_FAILED: 1700 { 1701 rc = VERR_CANCELLED; 1702 break; 1703 } 1704 1705 case WAIT_TIMEOUT: 1706 { 1707 rc = VERR_TIMEOUT; 1708 break; 1709 } 1710 1711 default: 1712 { 1713 dwObj = WAIT_OBJECT_0 + cEvents - 1; 1714 if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_NOTIFY]) 1715 { 1716 LogFlowFunc(("Notify\n")); 1717 } 1718 else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_INPUT]) 1719 { 1720 1721 } 1722 else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_OUTPUT]) 1723 { 1724 DWORD cbPlayPos; 1725 hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pThis->pStrmOut->pDSB, NULL, &cbPlayPos); 1726 LogFlowFunc(("Output: hr=%Rhrc, dwPlayPos=%ld\n", hr, cbPlayPos)); 1727 } 1728 break; 1729 } 1730 } 1731 1732 if (pThis->fShutdown) 1733 break; 1734 1735 } while (RT_SUCCESS(rc)); 1736 1737 pThis->fStopped = true; 1738 1739 LogFlowFunc(("Exited with fShutdown=%RTbool, rc=%Rrc\n", pThis->fShutdown, rc)); 1740 return rc; 1741 } 1742 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ 1743 1557 1744 static DECLCALLBACK(void) drvHostDSoundShutdown(PPDMIHOSTAUDIO pInterface) 1558 1745 { 1559 NOREF(pInterface); 1746 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1747 1748 LogFlowFuncEnter(); 1749 1750 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1751 int rc = dsoundNotifyThread(pThis, true /* fShutdown */); 1752 AssertRC(rc); 1753 1754 int rcThread; 1755 rc = RTThreadWait(pThis->Thread, 15 * 1000 /* 15s timeout */, &rcThread); 1756 LogFlowFunc(("rc=%Rrc, rcThread=%Rrc\n", rc, rcThread)); 1757 1758 Assert(pThis->fStopped); 1759 1760 if (pThis->aEvents[DSOUNDEVENT_NOTIFY]) 1761 { 1762 CloseHandle(pThis->aEvents[DSOUNDEVENT_NOTIFY]); 1763 pThis->aEvents[DSOUNDEVENT_NOTIFY] = NULL; 1764 } 1765 #endif 1766 1767 LogFlowFuncLeave(); 1560 1768 } 1561 1769 … … 1565 1773 1566 1774 LogFlowFuncEnter(); 1775 1776 int rc; 1567 1777 1568 1778 /* Verify that IDirectSound is available. */ … … 1571 1781 IID_IDirectSound, (void **)&pDirectSound); 1572 1782 if (SUCCEEDED(hr)) 1783 { 1573 1784 IDirectSound_Release(pDirectSound); 1785 1786 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1787 /* Create notification event. */ 1788 pThis->aEvents[DSOUNDEVENT_NOTIFY] = CreateEvent(NULL /* Security attribute */, 1789 FALSE /* bManualReset */, FALSE /* bInitialState */, 1790 NULL /* lpName */); 1791 Assert(pThis->aEvents[DSOUNDEVENT_NOTIFY] != NULL); 1792 1793 /* Start notification thread. */ 1794 rc = RTThreadCreate(&pThis->Thread, drvHostDSoundThread, 1795 pThis /*pvUser*/, 0 /*cbStack*/, 1796 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "dSoundNtfy"); 1797 if (RT_SUCCESS(rc)) 1798 { 1799 /* Wait for the thread to initialize. */ 1800 rc = RTThreadUserWait(pThis->Thread, RT_MS_1MIN); 1801 if (RT_FAILURE(rc)) 1802 DSLOGREL(("DSound: Waiting for thread to initialize failed with rc=%Rrc\n", rc)); 1803 } 1804 else 1805 DSLOGREL(("DSound: Creating thread failed with rc=%Rrc\n", rc)); 1806 #endif 1807 } 1574 1808 else 1809 { 1575 1810 DSLOGREL(("DSound: DirectSound not available %Rhrc\n", hr)); 1576 1577 int rc = SUCCEEDED(hr) ? VINF_SUCCESS: VERR_NOT_SUPPORTED;1811 rc = VERR_NOT_SUPPORTED; 1812 } 1578 1813 1579 1814 LogFlowFuncLeaveRC(rc); … … 1673 1908 RTListInit(&pThis->lstDevInput); 1674 1909 RTListInit(&pThis->lstDevOutput); 1910 1911 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1912 pThis->fStopped = false; 1913 pThis->fShutdown = false; 1914 1915 RT_ZERO(pThis->aEvents); 1916 pThis->cEvents = 0; 1917 #endif 1675 1918 1676 1919 /* … … 1698 1941 "DirectSound Audio host driver", 1699 1942 /* fFlags */ 1700 1943 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT, 1701 1944 /* fClass. */ 1702 1945 PDM_DRVREG_CLASS_AUDIO,
Note:
See TracChangeset
for help on using the changeset viewer.