Changeset 88861 in vbox for trunk/src/VBox/Devices
- Timestamp:
- May 4, 2021 4:00:36 PM (4 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88853 r88861 2499 2499 * Copy data to the pre-buffer, ring-buffer style. 2500 2500 * 2501 * This is used in two slightly different situations: 2502 * 2503 * -# When the stream is started (enabled) and we only want to prebuffer up 2504 * to the threshold before pushing the data to the backend. We 2505 * typically use the max buffer size for this situation. 2506 * 2507 * -# When the backend sets the PDMAUDIOSTREAM_STS_PREPARING_SWITCH 2508 * status bit and we're preparing for a smooth switch over to a 2509 * different audio device. Most of the pre-buffered data should not be 2510 * played on the old device prior to the switch, due to the prebuffering 2511 * at the start of the stream. We only use the threshold size for this 2512 * case. 2501 * The @a cbMax parameter is almost always set to the threshold size, the 2502 * exception is when commiting the buffer and we want to top it off to reduce 2503 * the number of transfers to the backend (the first transfer may start 2504 * playback, so more data is better). 2513 2505 */ 2514 2506 static int drvAudioStreamPreBuffer(PDRVAUDIOSTREAM pStreamEx, const uint8_t *pbBuf, uint32_t cbBuf, uint32_t cbMax) … … 3218 3210 } 3219 3211 } 3220 3221 /*3222 * Deal with PDMAUDIOSTREAM_STS_PREPARING_SWITCH being set.3223 *3224 * Note! We don't care if it's cleared as the backend will call3225 * PDMIHOSTAUDIOPORT::pfnStreamNotifyDeviceChanged when that takes place.3226 */3227 if ( !(fOldState & PDMAUDIOSTREAM_STS_PREPARING_SWITCH)3228 && (fNewState & PDMAUDIOSTREAM_STS_PREPARING_SWITCH))3229 {3230 if (pStreamEx->Out.cbPreBufThreshold > 0)3231 {3232 switch (enmPlayState)3233 {3234 case DRVAUDIOPLAYSTATE_PREBUF:3235 case DRVAUDIOPLAYSTATE_PREBUF_OVERDUE:3236 case DRVAUDIOPLAYSTATE_NOPLAY:3237 case DRVAUDIOPLAYSTATE_PREBUF_COMMITTING: /* simpler */3238 pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_PREBUF_SWITCHING;3239 break;3240 case DRVAUDIOPLAYSTATE_PLAY:3241 pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_PLAY_PREBUF;3242 break;3243 case DRVAUDIOPLAYSTATE_PREBUF_SWITCHING:3244 case DRVAUDIOPLAYSTATE_PLAY_PREBUF:3245 break;3246 /* no default */3247 case DRVAUDIOPLAYSTATE_END:3248 case DRVAUDIOPLAYSTATE_INVALID:3249 break;3250 }3251 LogFunc(("PDMAUDIOSTREAM_STS_INITIALIZED was set: %s -> %s\n",3252 drvAudioPlayStateName(enmPlayState), drvAudioPlayStateName(pStreamEx->Out.enmPlayState) ));3253 }3254 else3255 LogFunc(("PDMAUDIOSTREAM_STS_PREPARING_SWITCH was set, but no pre-buffering configured.\n"));3256 }3257 3212 } 3258 3213 … … 3324 3279 == (pStreamEx->fStatus & (PDMAUDIOSTREAM_STS_ENABLED | PDMAUDIOSTREAM_STS_PAUSED)) 3325 3280 || !(pStreamEx->fStatus & PDMAUDIOSTREAM_STS_BACKEND_READY) 3326 || !(fBackendStatus & PDMAUDIOSTREAM_STS_INITIALIZED) ); 3327 3328 if (!( (pStreamEx->fLastBackendStatus ^ fBackendStatus) 3329 & (PDMAUDIOSTREAM_STS_INITIALIZED | PDMAUDIOSTREAM_STS_PREPARING_SWITCH))) 3281 || !(fBackendStatus & PDMAUDIOSTREAM_STS_INITIALIZED)); 3282 3283 if (!((pStreamEx->fLastBackendStatus ^ fBackendStatus) & PDMAUDIOSTREAM_STS_INITIALIZED)) 3330 3284 { /* no relevant change - likely */ } 3331 3285 else … … 3927 3881 3928 3882 /** 3883 * @interface_method_impl{PDMIHOSTAUDIOPORT,pfnStreamNotifyPreparingDeviceSwitch} 3884 */ 3885 static DECLCALLBACK(void) drvAudioHostPort_StreamNotifyPreparingDeviceSwitch(PPDMIHOSTAUDIOPORT pInterface, 3886 PPDMAUDIOBACKENDSTREAM pStream) 3887 { 3888 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IHostAudioPort); 3889 3890 /* 3891 * Backend stream to validated DrvAudio stream: 3892 */ 3893 AssertPtrReturnVoid(pStream); 3894 AssertReturnVoid(pStream->uMagic == PDMAUDIOBACKENDSTREAM_MAGIC); 3895 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream->pStream; 3896 AssertPtrReturnVoid(pStreamEx); 3897 AssertReturnVoid(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC); 3898 AssertReturnVoid(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC); 3899 LogFlowFunc(("pStreamEx=%p '%s'\n", pStreamEx, pStreamEx->Guest.Cfg.szName)); 3900 3901 /* 3902 * Grab the lock and do switch the state (only needed for output streams for now). 3903 */ 3904 RTCritSectEnter(&pThis->CritSect); 3905 AssertReturnVoidStmt(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, RTCritSectLeave(&pThis->CritSect)); /* paranoia */ 3906 3907 if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT) 3908 { 3909 if (pStreamEx->Out.cbPreBufThreshold > 0) 3910 { 3911 DRVAUDIOPLAYSTATE const enmPlayState = pStreamEx->Out.enmPlayState; 3912 switch (enmPlayState) 3913 { 3914 case DRVAUDIOPLAYSTATE_PREBUF: 3915 case DRVAUDIOPLAYSTATE_PREBUF_OVERDUE: 3916 case DRVAUDIOPLAYSTATE_NOPLAY: 3917 case DRVAUDIOPLAYSTATE_PREBUF_COMMITTING: /* simpler */ 3918 pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_PREBUF_SWITCHING; 3919 break; 3920 case DRVAUDIOPLAYSTATE_PLAY: 3921 pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_PLAY_PREBUF; 3922 break; 3923 case DRVAUDIOPLAYSTATE_PREBUF_SWITCHING: 3924 case DRVAUDIOPLAYSTATE_PLAY_PREBUF: 3925 break; 3926 /* no default */ 3927 case DRVAUDIOPLAYSTATE_END: 3928 case DRVAUDIOPLAYSTATE_INVALID: 3929 break; 3930 } 3931 LogFunc(("%s -> %s\n", drvAudioPlayStateName(enmPlayState), drvAudioPlayStateName(pStreamEx->Out.enmPlayState) )); 3932 } 3933 else 3934 LogFunc(("No pre-buffering configured.\n")); 3935 } 3936 else 3937 LogFunc(("input stream, nothing to do.\n")); 3938 3939 RTCritSectLeave(&pThis->CritSect); 3940 } 3941 3942 3943 /** 3929 3944 * @interface_method_impl{PDMIHOSTAUDIOPORT,pfnStreamNotifyDeviceChanged} 3930 3945 */ … … 3964 3979 pStreamEx->fStatus &= ~PDMAUDIOSTREAM_STS_NEED_REINIT); 3965 3980 3966 if ( pStreamEx->Core.enmDir == PDMAUDIODIR_OUT 3967 && (pStreamEx->fStatus & PDMAUDIOSTREAM_STS_ENABLED))3981 3982 if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT) 3968 3983 { 3969 3984 DRVAUDIOPLAYSTATE const enmPlayState = pStreamEx->Out.enmPlayState; 3970 3985 pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_PREBUF; 3971 3986 LogFunc(("%s: %s -> %s\n", pStreamEx->Core.szName, drvAudioPlayStateName(enmPlayState), 3972 drvAudioPlayStateName(pStreamEx->Out.enmPlayState) )); RT_NOREF(enmPlayState); 3973 } 3987 drvAudioPlayStateName(pStreamEx->Out.enmPlayState) )); 3988 RT_NOREF(enmPlayState); 3989 } 3990 3991 /* Disable and then fully resync. */ 3992 /** @todo This doesn't work quite reliably if we're in draining mode 3993 * (PENDING_DISABLE, so the backend needs to take care of that prior to calling 3994 * us. Sigh. The idea was to avoid extra state mess in the backend... */ 3995 drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 3996 drvAudioStreamUpdateBackendOnStatus(pThis, pStreamEx, "device changed"); 3974 3997 } 3975 3998 … … 4659 4682 pThis->IAudioConnector.pfnStreamCapture = drvAudioStreamCapture; 4660 4683 /* IHostAudioPort */ 4661 pThis->IHostAudioPort.pfnDoOnWorkerThread = drvAudioHostPort_DoOnWorkerThread; 4662 pThis->IHostAudioPort.pfnNotifyDeviceChanged = drvAudioHostPort_NotifyDeviceChanged; 4663 pThis->IHostAudioPort.pfnStreamNotifyDeviceChanged = drvAudioHostPort_StreamNotifyDeviceChanged; 4664 pThis->IHostAudioPort.pfnNotifyDevicesChanged = drvAudioHostPort_NotifyDevicesChanged; 4684 pThis->IHostAudioPort.pfnDoOnWorkerThread = drvAudioHostPort_DoOnWorkerThread; 4685 pThis->IHostAudioPort.pfnNotifyDeviceChanged = drvAudioHostPort_NotifyDeviceChanged; 4686 pThis->IHostAudioPort.pfnStreamNotifyPreparingDeviceSwitch = drvAudioHostPort_StreamNotifyPreparingDeviceSwitch; 4687 pThis->IHostAudioPort.pfnStreamNotifyDeviceChanged = drvAudioHostPort_StreamNotifyDeviceChanged; 4688 pThis->IHostAudioPort.pfnNotifyDevicesChanged = drvAudioHostPort_NotifyDevicesChanged; 4665 4689 4666 4690 /* -
trunk/src/VBox/Devices/Audio/DrvHostAudioWasApi.cpp
r88853 r88861 39 39 40 40 #include <iprt/rand.h> 41 #include <iprt/semaphore.h> 41 42 #include <iprt/utf16.h> 42 43 #include <iprt/uuid.h> … … 63 64 /** @name DRVHOSTAUDIOWAS_DO_XXX - Worker thread operations. 64 65 * @{ */ 65 #define DRVHOSTAUDIOWAS_DO_PURGE_CACHE ((uintptr_t)0x49f37300 + 1) 66 #define DRVHOSTAUDIOWAS_DO_PURGE_CACHE ((uintptr_t)0x49f37300 + 1) 67 #define DRVHOSTAUDIOWAS_DO_STREAM_DEV_SWITCH ((uintptr_t)0x49f37300 + 2) 66 68 /** @} */ 67 69 … … 168 170 /** Set if we should restart the stream on resume (saved pause state). */ 169 171 bool fRestartOnResume; 172 /** Set if we're switching to a new output/input device. */ 173 bool fSwitchingDevice; 170 174 171 175 /** The RTTimeMilliTS() deadline for the draining of this stream (output). */ … … 251 255 /** Serializing access to CacheHead. */ 252 256 RTCRITSECT CritSectCache; 257 /** Semaphore for signalling that cache purge is done and that the destructor 258 * can do cleanups. */ 259 RTSEMEVENTMULTI hEvtCachePurge; 253 260 254 261 #if 0 … … 578 585 m_pDrvWas->pIDeviceInput = pIDevice; 579 586 } 580 581 /** @todo Invalid/update in-use streams. */582 587 } 583 588 else if (pIDevice) … … 778 783 * Purges all the entries in the cache. 779 784 */ 780 static void drvHostAudioWasCachePurge(PDRVHOSTAUDIOWAS pThis )785 static void drvHostAudioWasCachePurge(PDRVHOSTAUDIOWAS pThis, bool fOnWorker) 781 786 { 782 787 for (;;) … … 788 793 break; 789 794 drvHostAudioWasCacheDestroyDevEntry(pDevEntry); 795 } 796 797 if (fOnWorker) 798 { 799 int rc = RTSemEventMultiSignal(pThis->hEvtCachePurge); 800 AssertRC(rc); 790 801 } 791 802 } … … 1049 1060 * 1050 1061 * @returns VBox status code. 1062 * @retval VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED if @a fOnWorker is @c false and 1063 * we created a new entry that needs initalization by calling 1064 * drvHostAudioWasCacheInitConfig() on it. 1051 1065 * @param pThis The WASAPI host audio driver instance data. 1052 1066 * @param pIDevice The device to look up. 1053 1067 * @param pCfgReq The configuration to look up. 1054 * @param fOnWorker Set if we're on a worker thread, otherwise false. 1068 * @param fOnWorker Set if we're on a worker thread, otherwise false. When 1069 * set to @c true, VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED will 1070 * not be returned and a new entry will be fully 1071 * initialized before returning. 1055 1072 * @param ppDevCfg Where to return the requested device config. 1056 1073 */ … … 1290 1307 AssertBreak(Msg.lParam == 0); 1291 1308 1292 drvHostAudioWasCachePurge(pThis );1309 drvHostAudioWasCachePurge(pThis, false /*fOnWorker*/); 1293 1310 break; 1294 1311 } … … 1304 1321 1305 1322 LogFlowFunc(("Pre-quit cache purge...\n")); 1306 drvHostAudioWasCachePurge(pThis );1323 drvHostAudioWasCachePurge(pThis, false /*fOnWorker*/); 1307 1324 1308 1325 LogFunc(("Quits\n")); … … 1526 1543 1527 1544 /** 1545 * Performs the actual switching of device config. 1546 * 1547 * Worker for drvHostAudioWasDoStreamDevSwitch() and 1548 * drvHostAudioWasHA_StreamNotifyDeviceChanged(). 1549 */ 1550 static void drvHostAudioWasCompleteStreamDevSwitch(PDRVHOSTAUDIOWAS pThis, PDRVHOSTAUDIOWASSTREAM pStreamWas, 1551 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg) 1552 { 1553 RTCritSectEnter(&pStreamWas->CritSect); 1554 1555 /* Do the switch. */ 1556 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfgOld = pStreamWas->pDevCfg; 1557 pStreamWas->pDevCfg = pDevCfg; 1558 1559 /* The new stream is neither started nor draining. */ 1560 pStreamWas->fStarted = false; 1561 pStreamWas->fDraining = false; 1562 1563 /* Device switching is done now. */ 1564 pStreamWas->fSwitchingDevice = false; 1565 1566 /* Stop the old stream or Reset() will fail when putting it back into the cache. */ 1567 if (pStreamWas->fEnabled && pDevCfgOld->pIAudioClient) 1568 pDevCfgOld->pIAudioClient->Stop(); 1569 1570 RTCritSectLeave(&pStreamWas->CritSect); 1571 1572 /* Notify DrvAudio. */ 1573 pThis->pIHostAudioPort->pfnStreamNotifyDeviceChanged(pThis->pIHostAudioPort, &pStreamWas->Core, false /*fReInit*/); 1574 1575 /* Put the old config back into the cache. */ 1576 drvHostAudioWasCachePutBack(pThis, pDevCfgOld); 1577 1578 LogFlowFunc(("returns with '%s' state: %s\n", pStreamWas->Cfg.szName, drvHostWasStreamStatusString(pStreamWas) )); 1579 } 1580 1581 1582 /** 1583 * Called on a worker thread to initialize a new device config and switch the 1584 * given stream to using it. 1585 * 1586 * @sa drvHostAudioWasHA_StreamNotifyDeviceChanged 1587 */ 1588 static void drvHostAudioWasDoStreamDevSwitch(PDRVHOSTAUDIOWAS pThis, PDRVHOSTAUDIOWASSTREAM pStreamWas, 1589 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg) 1590 { 1591 /* 1592 * Do the initializing. 1593 */ 1594 int rc = drvHostAudioWasCacheInitConfig(pDevCfg); 1595 if (RT_SUCCESS(rc)) 1596 drvHostAudioWasCompleteStreamDevSwitch(pThis, pStreamWas, pDevCfg); 1597 else 1598 { 1599 LogRelMax(64, ("WasAPI: Failed to set up new device config '%ls:%s' for stream '%s': %Rrc\n", 1600 pDevCfg->pDevEntry->wszDevId, pDevCfg->szProps, pStreamWas->Cfg.szName, rc)); 1601 drvHostAudioWasCacheDestroyDevConfig(pDevCfg); 1602 pThis->pIHostAudioPort->pfnStreamNotifyDeviceChanged(pThis->pIHostAudioPort, &pStreamWas->Core, true /*fReInit*/); 1603 } 1604 } 1605 1606 1607 /** 1528 1608 * @interface_method_impl{PDMIHOSTAUDIO,pfnDoOnWorkerThread} 1529 1609 */ … … 1532 1612 { 1533 1613 PDRVHOSTAUDIOWAS pThis = RT_FROM_MEMBER(pInterface, DRVHOSTAUDIOWAS, IHostAudio); 1534 RT_NOREF(pStream, pvUser);1535 1614 LogFlowFunc(("uUser=%#zx pStream=%p pvUser=%p\n", uUser, pStream, pvUser)); 1536 1615 … … 1540 1619 Assert(pStream == NULL); 1541 1620 Assert(pvUser == NULL); 1542 drvHostAudioWasCachePurge(pThis); 1621 drvHostAudioWasCachePurge(pThis, true /*fOnWorker*/); 1622 break; 1623 1624 case DRVHOSTAUDIOWAS_DO_STREAM_DEV_SWITCH: 1625 AssertPtr(pStream); 1626 AssertPtr(pvUser); 1627 drvHostAudioWasDoStreamDevSwitch(pThis, (PDRVHOSTAUDIOWASSTREAM)pStream, (PDRVHOSTAUDIOWASCACHEDEVCFG)pvUser); 1543 1628 break; 1544 1629 … … 1777 1862 LogFlowFunc(("returns\n")); 1778 1863 return VINF_SUCCESS; 1864 } 1865 1866 1867 /** 1868 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamNotifyDeviceChanged} 1869 */ 1870 static DECLCALLBACK(void) drvHostAudioWasHA_StreamNotifyDeviceChanged(PPDMIHOSTAUDIO pInterface, 1871 PPDMAUDIOBACKENDSTREAM pStream, void *pvUser) 1872 { 1873 PDRVHOSTAUDIOWAS pThis = RT_FROM_MEMBER(pInterface, DRVHOSTAUDIOWAS, IHostAudio); 1874 PDRVHOSTAUDIOWASSTREAM pStreamWas = (PDRVHOSTAUDIOWASSTREAM)pStream; 1875 LogFlowFunc(("pStreamWas=%p (%s)\n", pStreamWas, pStreamWas->Cfg.szName)); 1876 RT_NOREF(pvUser); 1877 1878 /* 1879 * See if we've got a cached config for the new device around. 1880 * We ignore this entirely, for now at least, if the device was 1881 * disconnected and there is no replacement. 1882 */ 1883 pThis->pNotifyClient->lockEnter(); 1884 IMMDevice *pIDevice = pStreamWas->Cfg.enmDir == PDMAUDIODIR_IN ? pThis->pIDeviceInput : pThis->pIDeviceOutput; 1885 if (pIDevice) 1886 pIDevice->AddRef(); 1887 pThis->pNotifyClient->lockLeave(); 1888 if (pIDevice) 1889 { 1890 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg = NULL; 1891 int rc = drvHostAudioWasCacheLookupOrCreate(pThis, pIDevice, &pStreamWas->Cfg, false /*fOnWorker*/, &pDevCfg); 1892 1893 pIDevice->Release(); 1894 pIDevice = NULL; 1895 1896 /* 1897 * If we have a working audio client, just do the switch. 1898 */ 1899 if (RT_SUCCESS(rc) && pDevCfg->pIAudioClient) 1900 { 1901 LogFlowFunc(("New device config is ready already!\n")); 1902 Assert(rc == VINF_SUCCESS); 1903 drvHostAudioWasCompleteStreamDevSwitch(pThis, pStreamWas, pDevCfg); 1904 } 1905 /* 1906 * Otherwise create one asynchronously on a worker thread. 1907 */ 1908 else if (RT_SUCCESS(rc)) 1909 { 1910 LogFlowFunc(("New device config needs async init ...\n")); 1911 Assert(rc == VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED); 1912 1913 RTCritSectEnter(&pStreamWas->CritSect); 1914 pStreamWas->fSwitchingDevice = true; 1915 RTCritSectLeave(&pStreamWas->CritSect); 1916 1917 pThis->pIHostAudioPort->pfnStreamNotifyPreparingDeviceSwitch(pThis->pIHostAudioPort, &pStreamWas->Core); 1918 1919 rc = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, &pStreamWas->Core, 1920 DRVHOSTAUDIOWAS_DO_STREAM_DEV_SWITCH, pDevCfg); 1921 AssertRCStmt(rc, drvHostAudioWasDoStreamDevSwitch(pThis, pStreamWas, pDevCfg)); 1922 } 1923 else 1924 { 1925 LogRelMax(64, ("WasAPI: Failed to create new device config '%ls:%s' for stream '%s': %Rrc\n", 1926 pDevCfg->pDevEntry->wszDevId, pDevCfg->szProps, pStreamWas->Cfg.szName, rc)); 1927 1928 pThis->pIHostAudioPort->pfnStreamNotifyDeviceChanged(pThis->pIHostAudioPort, &pStreamWas->Core, true /*fReInit*/); 1929 } 1930 } 1931 else 1932 LogFlowFunc(("no new device, leaving it as-is\n")); 1779 1933 } 1780 1934 … … 2283 2437 } 2284 2438 if (pStreamWas->fEnabled) 2439 { 2285 2440 fStrmStatus |= PDMAUDIOSTREAM_STS_ENABLED; 2286 if (pStreamWas->fDraining) 2287 fStrmStatus |= PDMAUDIOSTREAM_STS_PENDING_DISABLE; 2288 if (pStreamWas->fRestartOnResume) 2289 fStrmStatus |= PDMAUDIOSTREAM_STS_PAUSED; 2441 if (pStreamWas->fDraining) 2442 fStrmStatus |= PDMAUDIOSTREAM_STS_PENDING_DISABLE; 2443 if (pStreamWas->fRestartOnResume) 2444 fStrmStatus |= PDMAUDIOSTREAM_STS_PAUSED; 2445 } 2446 if (pStreamWas->fSwitchingDevice) 2447 fStrmStatus |= PDMAUDIOSTREAM_STS_PREPARING_SWITCH; 2290 2448 2291 2449 LogFlowFunc(("returns %#x for '%s' {%s}\n", fStrmStatus, pStreamWas->Cfg.szName, drvHostWasStreamStatusString(pStreamWas))); … … 2628 2786 if (!RTListIsEmpty(&pThis->CacheHead) && pThis->pIHostAudioPort) 2629 2787 { 2630 int rc = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL/*pStream*/, 2788 int rc = RTSemEventMultiCreate(&pThis->hEvtCachePurge); 2789 if (RT_SUCCESS(rc)) 2790 { 2791 rc = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL/*pStream*/, 2631 2792 DRVHOSTAUDIOWAS_DO_PURGE_CACHE, NULL /*pvUser*/); 2632 AssertRC(rc); 2793 AssertRC(rc); 2794 } 2633 2795 } 2634 2796 #endif … … 2657 2819 LogFlowFuncEnter(); 2658 2820 2821 /* 2822 * Release the notification client first. 2823 */ 2659 2824 if (pThis->pNotifyClient) 2660 2825 { … … 2678 2843 if (RTCritSectIsInitialized(&pThis->CritSectCache)) 2679 2844 { 2680 drvHostAudioWasCachePurge(pThis); 2845 drvHostAudioWasCachePurge(pThis, false /*fOnWorker*/); 2846 if (pThis->hEvtCachePurge != NIL_RTSEMEVENTMULTI) 2847 RTSemEventMultiWait(pThis->hEvtCachePurge, RT_MS_30SEC); 2681 2848 RTCritSectDelete(&pThis->CritSectCache); 2849 } 2850 2851 if (pThis->hEvtCachePurge != NIL_RTSEMEVENTMULTI) 2852 { 2853 RTSemEventMultiDestroy(pThis->hEvtCachePurge); 2854 pThis->hEvtCachePurge = NIL_RTSEMEVENTMULTI; 2682 2855 } 2683 2856 … … 2722 2895 pThis->pDrvIns = pDrvIns; 2723 2896 pThis->hDrainTimer = NIL_TMTIMERHANDLE; 2897 pThis->hEvtCachePurge = NIL_RTSEMEVENTMULTI; 2724 2898 #if 0 2725 2899 pThis->hWorkerThread = NIL_RTTHREAD; … … 2739 2913 pThis->IHostAudio.pfnStreamInitAsync = drvHostAudioWasHA_StreamInitAsync; 2740 2914 pThis->IHostAudio.pfnStreamDestroy = drvHostAudioWasHA_StreamDestroy; 2741 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = NULL;2915 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = drvHostAudioWasHA_StreamNotifyDeviceChanged; 2742 2916 pThis->IHostAudio.pfnStreamControl = drvHostAudioWasHA_StreamControl; 2743 2917 pThis->IHostAudio.pfnStreamGetReadable = drvHostAudioWasHA_StreamGetReadable;
Note:
See TracChangeset
for help on using the changeset viewer.