VirtualBox

Changeset 70916 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Feb 8, 2018 3:53:53 PM (7 years ago)
Author:
vboxsync
Message:

Audio/DrvHostDSound.cpp: Use the notification thread by default to achieve a (hopefully) better audio output result. Work in progress.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r70888 r70916  
    7070    } while (0)
    7171
    72 
    7372/** Maximum number of attempts to restore the sound buffer before giving up. */
    7473#define DRV_DSOUND_RESTORE_ATTEMPTS_MAX         3
     74/** Default input latency (in ms). */
     75#define DRV_DSOUND_DEFAULT_LATENCY_MS_IN        50
     76/** Default output latency (in ms). */
     77#define DRV_DSOUND_DEFAULT_LATENCY_MS_OUT       50
    7578
    7679/** Makes DRVHOSTDSOUND out of PDMIHOSTAUDIO. */
     
    9093typedef FNDIRECTSOUNDCAPTURECREATE8 *PFNDIRECTSOUNDCAPTURECREATE8;
    9194
    92 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    93 # define VBOX_DSOUND_MAX_EVENTS 3
     95#define VBOX_DSOUND_MAX_EVENTS 3
    9496
    9597typedef enum DSOUNDEVENT
     
    98100    DSOUNDEVENT_INPUT,
    99101    DSOUNDEVENT_OUTPUT,
    100  } DSOUNDEVENT;
    101 #endif /* VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS */
     102} DSOUNDEVENT;
    102103
    103104typedef struct DSOUNDHOSTCFG
    104105{
    105     DWORD   cbBufferIn;
    106     DWORD   cbBufferOut;
    107     RTUUID  uuidPlay;
    108     LPCGUID pGuidPlay;
    109     RTUUID  uuidCapture;
    110     LPCGUID pGuidCapture;
     106    unsigned int    msLatencyIn;
     107    unsigned int    msLatencyOut;
     108    RTUUID          uuidPlay;
     109    LPCGUID         pGuidPlay;
     110    RTUUID          uuidCapture;
     111    LPCGUID         pGuidCapture;
    111112} DSOUNDHOSTCFG, *PDSOUNDHOSTCFG;
    112113
     
    119120    /** Whether this stream is in an enable state on the DirectSound side. */
    120121    bool               fEnabled;
     122    RTCRITSECT         CritSect;
    121123    union
    122124    {
     
    148150            DWORD                       cbBufSize;
    149151            /** Flag indicating whether playback was (re)started. */
    150             bool                        fRestartPlayback;
     152            bool                        fFirstPlayback;
     153            uint64_t tsLastPlayMs;
     154            bool fPendingPlayback;
     155            bool fPendingClose;
     156            PRTCIRCBUF                  pCircBuf;
    151157        } Out;
    152158    };
     
    166172    RTLISTANCHOR                lstDevOutput;
    167173    /** DirectSound configuration options. */
    168     DSOUNDHOSTCFG               cfg;
     174    DSOUNDHOSTCFG               Cfg;
    169175    /** Whether this backend supports any audio input. */
    170176    bool                        fEnabledIn;
     
    183189    PFNPDMHOSTAUDIOCALLBACK     pfnCallback;
    184190#endif
    185 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    186     /** Pointer to the audio connector interface of the driver/device above us. */
    187     PPDMIAUDIOCONNECTOR         pUpIAudioConnector;
    188191    /** Stopped indicator. */
    189192    bool                        fStopped;
     
    194197    /** Array of events to wait for in notification thread. */
    195198    HANDLE                      aEvents[VBOX_DSOUND_MAX_EVENTS];
    196     /** Number of events to wait for in notification thread.
    197      *  Must not exceed VBOX_DSOUND_MAX_EVENTS. */
    198     uint8_t                     cEvents;
    199199    /** Pointer to the input stream. */
    200200    PDSOUNDSTREAM               pDSStrmIn;
    201201    /** Pointer to the output stream. */
    202202    PDSOUNDSTREAM               pDSStrmOut;
    203 #endif
    204203} DRVHOSTDSOUND, *PDRVHOSTDSOUND;
    205204
     
    236235*********************************************************************************************************************************/
    237236static HRESULT  directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB);
     237static HRESULT  directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush);
    238238static HRESULT  directSoundCaptureStop(PDSOUNDSTREAM pStreamDS);
    239239
    240240static void     dsoundDeviceRemove(PDSOUNDDEV pDev);
    241241static int      dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg);
    242 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
     242
    243243static int      dsoundNotifyThread(PDRVHOSTDSOUND pThis, bool fShutdown);
    244 #endif
     244
    245245static void     dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis);
    246246static void     dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum);
     
    401401    HRESULT hr = IDirectSoundBuffer8_Restore(pDSB);
    402402    if (FAILED(hr))
     403        DSLOG(("DSound: Restoring playback buffer\n"));
     404    else
    403405        DSLOGREL(("DSound: Restoring playback buffer failed with %Rhrc\n", hr));
     406
    404407    return hr;
    405408}
     
    435438                                   DWORD dwFlags)
    436439{
     440    AssertReturn(dwBytes, VERR_INVALID_PARAMETER);
     441
    437442    HRESULT hr = E_FAIL;
    438443    AssertCompile(DRV_DSOUND_RESTORE_ATTEMPTS_MAX > 0);
     
    470475    }
    471476
    472     DSLOGREL(("DSound: Locking playback buffer failed with %Rhrc\n", hr));
     477    DSLOGREL(("DSound: Locking playback buffer failed with %Rhrc (dwOff=%ld, dwBytes=%ld)\n", hr, dwOffset, dwBytes));
    473478    return hr;
    474479}
     
    543548    else
    544549    {
    545         hr = IDirectSound8_Initialize(pThis->pDS, pThis->cfg.pGuidPlay);
     550        hr = IDirectSound8_Initialize(pThis->pDS, pThis->Cfg.pGuidPlay);
    546551        if (SUCCEEDED(hr))
    547552        {
     
    573578    AssertPtrReturn(pStreamDS, E_POINTER);
    574579
    575     HRESULT hr = S_OK;
    576 
    577     if (pStreamDS->Out.pDSB)
    578     {
    579         DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pStreamDS, pStreamDS->Out.pDSB));
    580 
    581         hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
    582         if (SUCCEEDED(hr))
    583         {
    584 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    585             if (pThis->aEvents[DSOUNDEVENT_OUTPUT] != NULL)
    586             {
    587                 CloseHandle(pThis->aEvents[DSOUNDEVENT_OUTPUT]);
    588                 pThis->aEvents[DSOUNDEVENT_OUTPUT] = NULL;
    589 
    590                 if (pThis->cEvents)
    591                     pThis->cEvents--;
    592 
    593                 pThis->pDSStrmOut = NULL;
    594             }
    595 
    596             int rc2 = dsoundNotifyThread(pThis, false /* fShutdown */);
    597             AssertRC(rc2);
    598 #endif
     580    LogFlowFuncEnter();
     581
     582    HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
     583    if (FAILED(hr))
     584        return hr;
     585
     586    DSLOG(("DSound: Closing playback stream\n"));
     587
     588    if (pStreamDS->Out.pCircBuf)
     589        Assert(RTCircBufUsed(pStreamDS->Out.pCircBuf) == 0);
     590
     591    if (SUCCEEDED(hr))
     592    {
     593        RTCritSectEnter(&pThis->CritSect);
     594
     595        if (pStreamDS->Out.pCircBuf)
     596        {
     597            RTCircBufDestroy(pStreamDS->Out.pCircBuf);
     598            pStreamDS->Out.pCircBuf = NULL;
     599        }
     600
     601        if (pStreamDS->Out.pDSB)
     602        {
    599603            IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB);
    600604            pStreamDS->Out.pDSB = NULL;
    601605        }
     606
     607        pThis->pDSStrmOut = NULL;
     608
     609        RTCritSectLeave(&pThis->CritSect);
     610
     611        int rc2 = dsoundNotifyThread(pThis, false /* fShutdown */);
     612        AssertRC(rc2);
    602613    }
    603614
     
    617628    AssertPtrReturn(pCfgAcq,   E_POINTER);
    618629
    619     DSLOG(("DSound: Opening playback stream %p: cbBufferOut=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
    620            pStreamDS,
    621            pThis->cfg.cbBufferOut,
     630    LogFlowFuncEnter();
     631
     632    Assert(pStreamDS->Out.pDSB == NULL);
     633
     634    DSLOG(("DSound: Opening playback stream (uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool)\n",
    622635           pCfgReq->Props.uHz,
    623636           pCfgReq->Props.cChannels,
    624637           pCfgReq->Props.cBits,
    625638           pCfgReq->Props.fSigned));
    626 
    627     if (pStreamDS->Out.pDSB != NULL)
    628     {
    629         /* Should not happen but be forgiving. */
    630         DSLOGREL(("DSound: Playback buffer already exists\n"));
    631         directSoundPlayClose(pThis, pStreamDS);
    632     }
    633639
    634640    WAVEFORMATEX wfx;
     
    682688         */
    683689        bd.dwFlags     = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE;
    684 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    685690        bd.dwFlags    |= DSBCAPS_CTRLPOSITIONNOTIFY;
    686 #endif
    687         bd.dwBufferBytes = pThis->cfg.cbBufferOut;
     691
     692        bd.dwBufferBytes = DrvAudioHlpCalcBitrate(&pCfgReq->Props) / 8;
     693
     694        DSLOG(("DSound: Playback buffer is %ld bytes\n", bd.dwBufferBytes));
    688695
    689696        hr = IDirectSound8_CreateSoundBuffer(pThis->pDS, &bd, &pDSB, NULL);
     
    750757                      bc.dwBufferBytes, pStreamDS->uAlign + 1));
    751758
    752         if (bc.dwBufferBytes != pThis->cfg.cbBufferOut)
    753             DSLOGREL(("DSound: Playback buffer size mismatched: DirectSound %RU32, requested %RU32 bytes\n",
    754                       bc.dwBufferBytes, pThis->cfg.cbBufferOut));
    755 
    756759        /*
    757760         * Initial state.
     
    760763         */
    761764        pStreamDS->Out.cbBufSize = bc.dwBufferBytes;
    762         DSLOG(("DSound: cMaxSamplesInBuffer=%RU32\n", pStreamDS->Out.cbBufSize));
    763 
    764 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
     765
     766        RTCritSectEnter(&pThis->CritSect);
     767
     768        rc = RTCircBufCreate(&pStreamDS->Out.pCircBuf, pStreamDS->Out.cbBufSize);
     769        AssertRC(rc);
     770
    765771        /*
    766772         * Install notification.
    767773         */
    768         pThis->aEvents[DSOUNDEVENT_OUTPUT] = CreateEvent(NULL /* Security attribute */,
    769                                                          FALSE /* bManualReset */, FALSE /* bInitialState */,
    770                                                          NULL /* lpName */);
    771         if (pThis->aEvents[DSOUNDEVENT_OUTPUT] == NULL)
    772         {
    773             hr = HRESULT_FROM_WIN32(GetLastError());
    774             DSLOGREL(("DSound: CreateEvent for output failed with %Rhrc\n", hr));
    775             break;
    776         }
    777 
    778774        LPDIRECTSOUNDNOTIFY8 pNotify;
    779775        hr = IDirectSoundNotify_QueryInterface(pStreamDS->Out.pDSB, IID_IDirectSoundNotify8, (PVOID *)&pNotify);
    780776        if (SUCCEEDED(hr))
    781777        {
    782             DSBPOSITIONNOTIFY dsBufPosNotify;
    783             RT_ZERO(dsBufPosNotify);
    784             dsBufPosNotify.dwOffset     = DSBPN_OFFSETSTOP;
    785             dsBufPosNotify.hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT];
    786 
    787             hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 1 /* Count */, &dsBufPosNotify);
     778            DSBPOSITIONNOTIFY dsPosNotify[3];
     779            RT_ZERO(dsPosNotify);
     780
     781            dsPosNotify[0].dwOffset     = 0;
     782            dsPosNotify[0].hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT];
     783
     784            dsPosNotify[1].dwOffset     = float(pStreamDS->Out.cbBufSize * 0.3);
     785            dsPosNotify[1].hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT];
     786
     787            dsPosNotify[2].dwOffset     = float(pStreamDS->Out.cbBufSize * 0.6);
     788            dsPosNotify[2].hEventNotify = pThis->aEvents[DSOUNDEVENT_OUTPUT];
     789
     790            hr = IDirectSoundNotify_SetNotificationPositions(pNotify, 3 /* Count */, dsPosNotify);
    788791            if (FAILED(hr))
    789792                DSLOGREL(("DSound: Setting playback position notification failed with %Rhrc\n", hr));
    790793
    791794            IDirectSoundNotify_Release(pNotify);
     795
     796            pThis->pDSStrmOut = pStreamDS;
    792797        }
    793798        else
    794799            DSLOGREL(("DSound: Querying interface for position notification failed with %Rhrc\n", hr));
    795800
    796         if (FAILED(hr))
    797             break;
    798 
    799         pThis->pDSStrmOut = pStreamDS;
    800 
    801         Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS);
    802         pThis->cEvents++;
    803 
    804         /* Let the thread know. */
    805         dsoundNotifyThread(pThis, false /* fShutdown */);
    806 
    807         /* Trigger the just installed output notification. */
    808         hr = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, 0);
    809         if (FAILED(hr))
    810             break;
    811 
    812 #endif /* VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS */
    813 
    814         pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pThis->cfg.cbBufferOut);
     801        RTCritSectLeave(&pThis->CritSect);
     802
     803        pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pStreamDS->Out.cbBufSize);
    815804
    816805    } while (0);
     
    889878
    890879
    891 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     880static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush)
    892881{
    893882    AssertPtrReturn(pThis,     E_POINTER);
     
    900889        if (pStreamDS->fEnabled)
    901890        {
    902             DSLOG(("DSound: Stopping playback\n"));
     891            DSLOG(("DSound: %s playback\n", fFlush ? "Stopping" : "Pausing"));
    903892
    904893            hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
     
    910899            }
    911900
    912             if (SUCCEEDED(hr))
    913                 pStreamDS->fEnabled = false;
    914         }
     901            pStreamDS->fEnabled = false;
     902        }
     903    }
     904
     905    if (SUCCEEDED(hr))
     906    {
     907        if (fFlush)
     908            RTCircBufReset(pStreamDS->Out.pCircBuf);
    915909    }
    916910
    917911    if (FAILED(hr))
    918         DSLOGREL(("DSound: Stopping playback failed with %Rhrc\n", hr));
     912        DSLOGREL(("DSound: %s playback failed with %Rhrc\n", fFlush ? "Stopping" : "Pausing", hr));
    919913
    920914    return hr;
     
    927921    AssertPtrReturn(pStreamDS, E_POINTER);
    928922
    929     HRESULT hr;
    930     if (pStreamDS->Out.pDSB != NULL)
    931     {
    932         DWORD dwStatus;
    933         hr = directSoundPlayGetStatus(pThis, pStreamDS->Out.pDSB, &dwStatus);
    934         if (SUCCEEDED(hr))
    935         {
    936             if (dwStatus & DSBSTATUS_PLAYING)
    937             {
    938                 DSLOG(("DSound: Already playing\n"));
    939             }
    940             else
    941             {
    942                 dsoundPlayClearBuffer(pThis, pStreamDS);
    943 
    944                 pStreamDS->Out.fRestartPlayback = true;
    945                 pStreamDS->fEnabled             = true;
    946 
    947                 DSLOG(("DSound: Playback started\n"));
    948 
    949                 /*
    950                  * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlay,
    951                  * because it is necessary to put some samples into the buffer first.
    952                  */
    953             }
    954         }
    955     }
    956     else
    957         hr = E_UNEXPECTED;
    958 
    959     if (FAILED(hr))
    960         DSLOGREL(("DSound: Starting playback failed with %Rhrc\n", hr));
    961 
    962     return hr;
     923    Assert(pStreamDS->fEnabled == false);
     924
     925    pStreamDS->Out.fFirstPlayback = true;
     926    pStreamDS->fEnabled           = true;
     927
     928    DSLOG(("DSound: Playback started\n"));
     929
     930    return S_OK;
    963931}
    964932
     
    974942    int rc = VINF_SUCCESS;
    975943
    976     LPCGUID pGUID = pThis->cfg.pGuidCapture;
     944    LPCGUID pGUID = pThis->Cfg.pGuidCapture;
    977945    if (!pGUID)
    978946    {
     
    11051073    AssertPtrReturn(pStreamDS, E_POINTER);
    11061074
     1075    LogFlowFuncEnter();
     1076
    11071077    HRESULT hr = S_OK;
    11081078
     
    11101080        && pStreamDS->In.pDSCB)
    11111081    {
    1112         DSLOG(("DSound: Closing capturing stream %p, buffer %p\n", pStreamDS, pStreamDS->In.pDSCB));
     1082        DSLOG(("DSound: Closing capturing stream\n"));
    11131083
    11141084        hr = directSoundCaptureStop(pStreamDS);
     
    11351105    AssertPtrReturn(pCfgAcq,   E_POINTER);
    11361106
    1137     DSLOG(("DSound: Opening capturing stream %p: cbBufferIn=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
    1138            pStreamDS,
    1139            pThis->cfg.cbBufferIn,
     1107    LogFlowFuncEnter();
     1108
     1109    Assert(pStreamDS->In.pDSCB == NULL);
     1110
     1111    DSLOG(("DSound: Opening capturing stream (uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool)\n",
    11401112           pCfgReq->Props.uHz,
    11411113           pCfgReq->Props.cChannels,
     
    11431115           pCfgReq->Props.fSigned));
    11441116
    1145     if (pStreamDS->In.pDSCB != NULL)
    1146     {
    1147         /* Should not happen but be forgiving. */
    1148         DSLOGREL(("DSound: DirectSoundCaptureBuffer already exists\n"));
    1149         directSoundCaptureClose(pStreamDS);
    1150     }
    1151 
    11521117    WAVEFORMATEX wfx;
    11531118    int rc = dsoundWaveFmtFromCfg(pCfgReq, &wfx);
     
    11631128    do /* To use breaks. */
    11641129    {
    1165         LPDIRECTSOUNDCAPTUREBUFFER pDSCB = NULL;
    1166 
    11671130        DSCBUFFERDESC bd;
    11681131        RT_ZERO(bd);
     
    11701133        bd.dwSize        = sizeof(bd);
    11711134        bd.lpwfxFormat   = &wfx;
    1172         bd.dwBufferBytes = pThis->cfg.cbBufferIn;
    1173 
     1135        bd.dwBufferBytes = DrvAudioHlpCalcBitrate(&pCfgReq->Props) / 8;
     1136
     1137        DSLOG(("DSound: Capture buffer is %ld bytes\n", bd.dwBufferBytes));
     1138
     1139        LPDIRECTSOUNDCAPTUREBUFFER pDSCB;
    11741140        hr = IDirectSoundCapture_CreateCaptureBuffer(pThis->pDSC, &bd, &pDSCB, NULL);
    11751141        if (FAILED(hr))
     
    12171183        if (FAILED(hr))
    12181184        {
    1219             DSLOGREL(("Getting capture capabilities failed with %Rhrc\n", hr));
     1185            DSLOGREL(("DSound: Getting capture capabilities failed with %Rhrc\n", hr));
    12201186            break;
    12211187        }
     
    12451211                      bc.dwBufferBytes, pStreamDS->uAlign + 1));
    12461212
    1247         if (bc.dwBufferBytes != pThis->cfg.cbBufferIn)
    1248             DSLOGREL(("DSound: Capture buffer size mismatched: DirectSound %RU32, requested %RU32 bytes\n",
    1249                       bc.dwBufferBytes, pThis->cfg.cbBufferIn));
    1250 
    12511213        /* Initial state: reading at the initial capture position, no error. */
    1252         pStreamDS->In.offReadPos = offByteReadPos;
    1253         pStreamDS->In.cbBufSize  = bc.dwBufferBytes;
    1254 
    1255         pStreamDS->In.hrLastCapture     = S_OK;
    1256 
    1257         DSLOG(("DSound: Opened capturing offReadPos=%RU32, cbBufSize=%RU32\n",
    1258                pStreamDS->In.offReadPos, pStreamDS->In.cbBufSize));
    1259 
    1260         pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, pThis->cfg.cbBufferIn);
     1214        pStreamDS->In.offReadPos    = offByteReadPos;
     1215        pStreamDS->In.cbBufSize     = bc.dwBufferBytes;
     1216        pStreamDS->In.hrLastCapture = S_OK;
     1217
     1218        pCfgAcq->cFrameBufferHint = PDMAUDIOSTREAMCFG_B2F(pCfgAcq, bc.dwBufferBytes);
    12611219
    12621220    } while (0);
     
    13171275            else
    13181276            {
    1319                 DWORD fFlags = 0;
    1320 #ifndef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    1321                 fFlags |= DSCBSTART_LOOPING;
    1322 #endif
     1277                const DWORD fFlags = DSCBSTART_LOOPING;
     1278
    13231279                DSLOG(("DSound: Starting to capture\n"));
    13241280                hr = IDirectSoundCaptureBuffer8_Start(pStreamDS->In.pDSCB, fFlags);
     
    15261482    if (RT_SUCCESS(rc))
    15271483    {
    1528 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
     1484#if 0
    15291485        if (   pThis->fEnabledOut != RT_BOOL(cbCtx.cDevOut)
    15301486            || pThis->fEnabledIn  != RT_BOOL(cbCtx.cDevIn))
     
    15331489             *        let the connector know that something has changed within the host backend. */
    15341490        }
    1535 #else
     1491#endif
    15361492        pThis->fEnabledOut = RT_BOOL(cbCtx.cDevOut);
    15371493        pThis->fEnabledIn  = RT_BOOL(cbCtx.cDevIn);
    1538 #endif
    15391494
    15401495        Cfg.cMaxStreamsIn  = UINT32_MAX;
     
    15651520    pStreamDS->Out.offPlayCursorLastPending = 0;
    15661521    pStreamDS->Out.cbWritten = 0;
    1567     pStreamDS->Out.fRestartPlayback = true;
     1522    pStreamDS->Out.fFirstPlayback = true;
     1523    pStreamDS->Out.fPendingPlayback = false;
     1524    pStreamDS->Out.tsLastPlayMs = 0;
    15681525    pStreamDS->Out.cbBufSize = 0;
    15691526
     
    15891546    {
    15901547        case PDMAUDIOSTREAMCMD_ENABLE:
    1591         case PDMAUDIOSTREAMCMD_RESUME:
    15921548        {
    15931549            hr = directSoundPlayStart(pThis, pStreamDS);
    15941550            if (FAILED(hr))
     1551                rc = VERR_NOT_SUPPORTED; /** @todo Fix this. */
     1552            break;
     1553        }
     1554
     1555        case PDMAUDIOSTREAMCMD_RESUME:
     1556        {
     1557            hr = directSoundPlayStart(pThis, pStreamDS);
     1558            if (SUCCEEDED(hr))
    15951559            {
    1596                 hr = directSoundPlayClose(pThis, pStreamDS);
    1597                 if (SUCCEEDED(hr))
    1598                 {
    1599                     PDMAUDIOSTREAMCFG CfgAcq;
    1600                     hr = directSoundPlayOpen(pThis, pStreamDS, pStreamDS->pCfg /* pCfqReq */, &CfgAcq);
    1601                     if (SUCCEEDED(hr))
    1602                     {
    1603                         DrvAudioHlpStreamCfgFree(pStreamDS->pCfg);
    1604 
    1605                         pStreamDS->pCfg = DrvAudioHlpStreamCfgDup(&CfgAcq);
    1606                         AssertPtr(pStreamDS->pCfg);
    1607 
    1608                         /** @todo What to do if the format has changed? */
    1609                     }
    1610                 }
    1611                 if (SUCCEEDED(hr))
    1612                     hr = directSoundPlayStart(pThis, pStreamDS);
     1560                BOOL fRc = SetEvent(pThis->aEvents[DSOUNDEVENT_OUTPUT]);
     1561                Assert(fRc);
    16131562            }
    16141563
     1564            if (FAILED(hr))
     1565                rc = VERR_NOT_SUPPORTED; /** @todo Fix this. */
     1566            break;
     1567        }
     1568
     1569        case PDMAUDIOSTREAMCMD_DISABLE:
     1570        case PDMAUDIOSTREAMCMD_PAUSE:
     1571        {
     1572            hr = directSoundPlayStop(pThis, pStreamDS, enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE /* fFlush */);
    16151573            if (FAILED(hr))
    16161574                rc = VERR_NOT_SUPPORTED;
     
    16181576        }
    16191577
    1620         case PDMAUDIOSTREAMCMD_DISABLE:
    1621         case PDMAUDIOSTREAMCMD_PAUSE:
    1622         {
    1623             AssertPtr(pThis->pDS);
    1624 
    1625             hr = directSoundPlayStop(pThis, pStreamDS);
    1626             if (FAILED(hr))
    1627                 rc = VERR_NOT_SUPPORTED;
    1628             break;
    1629         }
    1630 
    16311578        default:
    16321579        {
     
    16401587    return rc;
    16411588}
    1642 
    16431589
    16441590/**
     
    16611607    uint32_t cbWrittenTotal = 0;
    16621608
    1663 #ifdef DEBUG_andy
    1664     LogFlowFuncEnter();
    1665 #endif
    1666 
    1667     do /* to use 'break' */
    1668     {
    1669         AssertPtr(pStreamDS->pCfg);
    1670         PPDMAUDIOPCMPROPS pProps = &pStreamDS->pCfg->Props;
    1671 
    1672         DWORD cbFree;
    1673         rc = dsoundGetFreeOut(pThis, pStreamDS, &cbFree);
    1674         if (RT_FAILURE(rc))
    1675             break;
    1676 
    1677         if (pStreamDS->Out.fRestartPlayback == false)
    1678         {
    1679             DWORD offPlayCursor, offWriteCursor;
    1680             HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlayCursor, &offWriteCursor);
    1681             if (SUCCEEDED(hr))
    1682             {
    1683                 uint32_t cbPending;
    1684                 if (pStreamDS->Out.offPlayCursorLastPlayed <= offPlayCursor)
    1685                     cbPending = offPlayCursor - pStreamDS->Out.offPlayCursorLastPlayed;
    1686                 else
    1687                     cbPending = pStreamDS->Out.cbBufSize - pStreamDS->Out.offPlayCursorLastPlayed + offPlayCursor;
    1688 
    1689                 pStreamDS->Out.cbWritten               -= RT_MIN(pStreamDS->Out.cbWritten, cbPending);
    1690                 pStreamDS->Out.offPlayCursorLastPlayed  = offPlayCursor;
    1691             }
    1692         }
    1693 
    1694         /*
    1695          * Check for full buffer, do not allow the offPlayWritePos to catch cbPlayPos during playback,
    1696          * i.e. always leave a free space for 1 audio sample.
    1697          */
    1698         const DWORD cbSample = PDMAUDIOPCMPROPS_F2B(pProps, 1);
    1699         if (cbFree < cbSample)
    1700             break;
    1701         Assert(cbFree >= cbSample);
    1702         cbFree     -= cbSample;
    1703 
    1704         uint32_t cbLive = cxBuf;
    1705 
    1706         /* Do not write more than available space in the DirectSound playback buffer. */
    1707         cbLive  = RT_MIN(cbFree, cbLive);
    1708         cbLive &= ~pStreamDS->uAlign;
    1709 
    1710         if (!cbLive)
    1711             break;
    1712 
    1713         LPDIRECTSOUNDBUFFER8 pDSB = pStreamDS->Out.pDSB;
    1714         AssertPtr(pDSB);
    1715 
    1716         PVOID pv1, pv2;
    1717         DWORD cb1, cb2;
    1718         HRESULT hr = directSoundPlayLock(pThis, pStreamDS, pStreamDS->Out.offWritePos, cbLive,
    1719                                          &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);
    1720         if (FAILED(hr))
    1721         {
    1722             rc = VERR_ACCESS_DENIED;
    1723             break;
    1724         }
    1725 
    1726         AssertPtr(pv1);
    1727         Assert(cb1);
    1728 
    1729         memcpy(pv1, pvBuf, cb1);
    1730         cbWrittenTotal = cb1;
    1731 
    1732         if (pv2 && cb2) /* Buffer wrap-around? Write second part. */
    1733         {
    1734             memcpy(pv2, (uint8_t *)pvBuf + cb1, cb2);
    1735             cbWrittenTotal += cb2;
    1736         }
    1737 
    1738         Assert(cbLive == cb1 + cb2);
    1739 
    1740         directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2);
    1741 
    1742         pStreamDS->Out.offWritePos = (pStreamDS->Out.offWritePos + cbWrittenTotal) % pStreamDS->Out.cbBufSize;
    1743         pStreamDS->Out.cbWritten  += cbWrittenTotal;
    1744 
    1745         DSLOGF(("DSound: %RU32/%RU32, buffer write pos %ld, rc=%Rrc\n",
    1746                 cbWrittenTotal, cbLive, pStreamDS->Out.offWritePos, rc));
    1747 
    1748         if (pStreamDS->Out.fRestartPlayback)
    1749         {
    1750             /*
    1751              * The playback has been just started.
    1752              * Some samples of the new sound have been copied to the buffer
    1753              * and it can start playing.
    1754              */
    1755             pStreamDS->Out.fRestartPlayback = false;
    1756 
    1757             DWORD fFlags = 0;
    1758 #ifndef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    1759             fFlags |= DSCBSTART_LOOPING;
    1760 #endif
    1761             for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
    1762             {
    1763                 hr = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, fFlags);
    1764                 if (   SUCCEEDED(hr)
    1765                     || hr != DSERR_BUFFERLOST)
    1766                     break;
    1767                 else
    1768                 {
    1769                     LogFlowFunc(("Restarting playback failed due to lost buffer, restoring ...\n"));
    1770                     directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
    1771                 }
    1772             }
    1773 
    1774             if (FAILED(hr))
    1775             {
    1776                 DSLOGREL(("DSound: Starting playback failed with %Rhrc\n", hr));
    1777                 rc = VERR_NOT_SUPPORTED;
    1778                 break;
    1779             }
    1780         }
    1781 
    1782     } while (0);
     1609    uint8_t   *pbBuf    = (uint8_t *)pvBuf;
     1610    PRTCIRCBUF pCircBuf = pStreamDS->Out.pCircBuf;
     1611
     1612    uint32_t cbToPlay = RT_MIN(cxBuf, (uint32_t)RTCircBufFree(pCircBuf));
     1613    while (cbToPlay)
     1614    {
     1615        void *pvChunk;
     1616        size_t cbChunk;
     1617        RTCircBufAcquireWriteBlock(pCircBuf, cbToPlay, &pvChunk, &cbChunk);
     1618
     1619        if (cbChunk)
     1620        {
     1621            memcpy(pvChunk, pbBuf, cbChunk);
     1622
     1623            pbBuf     += cbChunk;
     1624            Assert(cbToPlay >= cbChunk);
     1625            cbToPlay  -= (uint32_t)cbChunk;
     1626
     1627            cbWrittenTotal += (uint32_t)cbChunk;
     1628        }
     1629
     1630        RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
     1631    }
     1632
     1633    Assert(cbWrittenTotal <= cxBuf);
     1634
     1635    if (   pStreamDS->Out.fFirstPlayback
     1636        && RTCircBufUsed(pCircBuf))
     1637    {
     1638        BOOL fRc = SetEvent(pThis->aEvents[DSOUNDEVENT_OUTPUT]);
     1639        Assert(fRc);
     1640
     1641//        Log3Func(("cxBuf=%RU32, cbWrittenTotal=%RU32, %RU64ms\n", cxBuf, cbWrittenTotal, tsNow - s_lastplayed));
     1642    }
    17831643
    17841644    if (RT_SUCCESS(rc))
     
    17981658    PDSOUNDSTREAM pStreamDS = (PDSOUNDSTREAM)pStream;
    17991659
    1800     directSoundPlayClose(pThis, pStreamDS);
     1660    LogFlowFuncEnter();
     1661
     1662    HRESULT hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
     1663    if (SUCCEEDED(hr))
     1664    {
     1665        hr = directSoundPlayClose(pThis, pStreamDS);
     1666        if (FAILED(hr))
     1667            return VERR_GENERAL_FAILURE; /** @todo Fix. */
     1668    }
    18011669
    18021670    return VINF_SUCCESS;
     
    20101878static int dsoundDestroyStreamIn(PDSOUNDSTREAM pStreamDS)
    20111879{
     1880    LogFlowFuncEnter();
     1881
    20121882    directSoundCaptureClose(pStreamDS);
    20131883
     
    20301900    return VINF_SUCCESS;
    20311901}
    2032 
    2033 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    20341902
    20351903static int dsoundNotifyThread(PDRVHOSTDSOUND pThis, bool fShutdown)
     
    20511919
    20521920
    2053 static DECLCALLBACK(int) dsoundNotificationThread(RTTHREAD hThreadSelf, void *pvUser)
     1921static DECLCALLBACK(int) dsoundThread(RTTHREAD hThreadSelf, void *pvUser)
    20541922{
    20551923    PDRVHOSTDSOUND pThis = (PDRVHOSTDSOUND)pvUser;
     
    20621930    AssertRC(rc);
    20631931
    2064     do
    2065     {
     1932    for (;;)
     1933    {
     1934        RTCritSectEnter(&pThis->CritSect);
     1935
    20661936        HANDLE aEvents[VBOX_DSOUND_MAX_EVENTS];
    20671937        DWORD  cEvents = 0;
     
    20731943        Assert(cEvents);
    20741944
    2075         LogFlowFunc(("Waiting: cEvents=%ld\n", cEvents));
     1945        RTCritSectLeave(&pThis->CritSect);
    20761946
    20771947        DWORD dwObj = WaitForMultipleObjects(cEvents, aEvents, FALSE /* bWaitAll */, INFINITE);
     1948
     1949        RTCritSectEnter(&pThis->CritSect);
     1950
    20781951        switch (dwObj)
    20791952        {
     
    20901963            }
    20911964
    2092             default:
     1965            case WAIT_OBJECT_0:
     1966            case WAIT_OBJECT_0 + 1:
     1967            case WAIT_OBJECT_0 + 2:
     1968            case WAIT_OBJECT_0 + 3:
     1969            case WAIT_OBJECT_0 + 4:
    20931970            {
    2094                 dwObj = WAIT_OBJECT_0 + cEvents - 1;
    2095                 if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_NOTIFY])
     1971                dwObj -= WAIT_OBJECT_0;
     1972
     1973                Log3Func(("Event %ld\n",  dwObj));
     1974
     1975                PDSOUNDSTREAM pStreamDS = pThis->pDSStrmOut;
     1976
     1977                if (!    pStreamDS
     1978                    ||  !pStreamDS->fEnabled)
     1979                    break;
     1980
     1981                if (dwObj == DSOUNDEVENT_NOTIFY)
    20961982                {
    2097                     LogFlowFunc(("Notify\n"));
    20981983                }
    2099                 else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_INPUT])
     1984                else if (dwObj == DSOUNDEVENT_INPUT)
    21001985                {
    2101 
    21021986                }
    2103                 else if (aEvents[dwObj] == pThis->aEvents[DSOUNDEVENT_OUTPUT])
     1987                else if (dwObj == DSOUNDEVENT_OUTPUT)
    21041988                {
    2105                     DWORD cbFree;
    2106                     rc = dsoundGetFreeOut(pThis->pDSStream, &cbFree);
    2107                     if (   RT_SUCCESS(rc)
    2108                         && cbFree)
     1989                    LPDIRECTSOUNDBUFFER8 pDSB = pStreamDS->Out.pDSB;
     1990                    if (!pDSB)
     1991                        break;
     1992
     1993                    HRESULT hr;
     1994
     1995                    DWORD offPlayCursor; DWORD offWriteCursor2;
     1996                    hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlayCursor, &offWriteCursor2);
     1997
     1998                    //Log3Func(("p=%ld, w=%ld\n", offPlayCursor, offWriteCursor2));
     1999
     2000                    DWORD cbFree, cbRemaining;
     2001                    if (pStreamDS->Out.fFirstPlayback)
    21092002                    {
    2110                         PDMAUDIOCBDATA_DATA_OUTPUT Out;
    2111                         Out.cbInFree     = cbFree;
    2112                         Out.cbOutWritten = 0;
    2113 
    2114                         while (!Out.cbOutWritten)
     2003                        DWORD offWriteCursor;
     2004                        hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, NULL, &offWriteCursor);
     2005                        if (FAILED(hr))
     2006                            break;
     2007
     2008                        pStreamDS->Out.offWritePos = offWriteCursor;
     2009
     2010                        cbFree      = pStreamDS->Out.cbBufSize;
     2011                        cbRemaining = pStreamDS->Out.cbBufSize;
     2012                    }
     2013                    else
     2014                    {
     2015                        DWORD offPlayCursor;
     2016                        hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlayCursor, NULL);
     2017                        if (FAILED(hr))
     2018                            break;
     2019
     2020                        cbFree      = dsoundRingDistance(offPlayCursor, pStreamDS->Out.offWritePos, pStreamDS->Out.cbBufSize);
     2021                        cbRemaining = dsoundRingDistance(pStreamDS->Out.offWritePos, offPlayCursor, pStreamDS->Out.cbBufSize);
     2022                    }
     2023
     2024                    PRTCIRCBUF pCircBuf = pStreamDS->Out.pCircBuf;
     2025                    AssertPtr(pCircBuf);
     2026
     2027                    DWORD cbUsed   = (uint32_t)RTCircBufUsed(pCircBuf);
     2028                    DWORD cbToPlay = RT_MIN(cbFree, cbUsed);
     2029
     2030                    //Log3Func(("cbUsed=%ld, cbToPlay=%ld\n", cbUsed, cbToPlay));
     2031
     2032                    while (cbToPlay)
     2033                    {
     2034                        void  *pvBuf;
     2035                        size_t cbBuf;
     2036                        RTCircBufAcquireReadBlock(pCircBuf, cbToPlay, &pvBuf, &cbBuf);
     2037
     2038                        if (cbBuf)
    21152039                        {
    2116                             rc = pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector,
    2117                                                                         PDMAUDIOCALLBACKTYPE_OUTPUT, &Out, sizeof(Out));
    2118                             if (RT_FAILURE(rc))
     2040                            PVOID pv1, pv2;
     2041                            DWORD cb1, cb2;
     2042                            hr = directSoundPlayLock(pThis, pStreamDS, pStreamDS->Out.offWritePos, (DWORD)cbBuf,
     2043                                                     &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);
     2044                            if (FAILED(hr))
    21192045                                break;
    2120                             RTThreadSleep(100);
     2046
     2047                            AssertPtr(pv1);
     2048                            Assert(cb1);
     2049
     2050                            memcpy(pv1, pvBuf, cb1);
     2051
     2052                            if (pv2 && cb2) /* Buffer wrap-around? Write second part. */
     2053                                memcpy(pv2, (uint8_t *)pvBuf + cb1, cb2);
     2054
     2055                            directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2);
     2056
     2057                            pStreamDS->Out.offWritePos = (pStreamDS->Out.offWritePos + cb1 + cb2) % pStreamDS->Out.cbBufSize;
     2058
     2059                            Assert(cbToPlay >= cbBuf);
     2060                            cbToPlay -= (uint32_t)cbBuf;
     2061
     2062                            pStreamDS->Out.cbWritten += cb1 + cb2;
    21212063                        }
    21222064
    2123                         LogFlowFunc(("Output: cbBuffer=%ld, cbFree=%ld, cbWritten=%RU32, rc=%Rrc\n",
    2124                                      cbBuffer, cbFree, Out.cbOutWritten, rc));
     2065                        RTCircBufReleaseReadBlock(pCircBuf, cbBuf);
     2066                    }
     2067
     2068                    if (pStreamDS->Out.fFirstPlayback)
     2069                    {
     2070                        DWORD fFlags = DSCBSTART_LOOPING;
     2071
     2072                        for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     2073                        {
     2074                            hr = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, fFlags);
     2075                            if (   SUCCEEDED(hr)
     2076                                || hr != DSERR_BUFFERLOST)
     2077                                break;
     2078                            else
     2079                            {
     2080                                LogFunc(("Restarting playback failed due to lost buffer, restoring ...\n"));
     2081                                directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
     2082                            }
     2083                        }
     2084
     2085                        if (SUCCEEDED(hr))
     2086                        {
     2087                            DSLOG(("DSound: Started playing output\n"));
     2088                            pStreamDS->Out.fFirstPlayback   = false;
     2089                            pStreamDS->Out.fPendingPlayback = true;
     2090                        }
     2091                    }
     2092                    else /* Continue playback */
     2093                    {
     2094                        if (   !RTCircBufUsed(pCircBuf)
     2095                            && !cbRemaining)
     2096                        {
     2097                            DSLOG(("DSound: Stopping playing output\n"));
     2098                            hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
     2099                        }
    21252100                    }
    21262101                }
    21272102                break;
    21282103            }
    2129         }
     2104
     2105            default:
     2106                AssertFailed();
     2107                break;
     2108        }
     2109
     2110        RTCritSectLeave(&pThis->CritSect);
    21302111
    21312112        if (pThis->fShutdown)
    21322113            break;
    21332114
    2134     } while (RT_SUCCESS(rc));
     2115    } /* for */
    21352116
    21362117    pThis->fStopped = true;
     
    21402121}
    21412122
    2142 #endif /* VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS */
    2143 
    2144 
    21452123/**
    21462124 * @interface_method_impl{PDMIHOSTAUDIO,pfnShutdown}
     
    21522130    LogFlowFuncEnter();
    21532131
    2154 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    21552132    int rc = dsoundNotifyThread(pThis, true /* fShutdown */);
    21562133    AssertRC(rc);
     
    21622139    Assert(pThis->fStopped);
    21632140
    2164     if (pThis->aEvents[DSOUNDEVENT_NOTIFY])
    2165     {
    2166         CloseHandle(pThis->aEvents[DSOUNDEVENT_NOTIFY]);
    2167         pThis->aEvents[DSOUNDEVENT_NOTIFY] = NULL;
    2168     }
    2169 #else
    2170     RT_NOREF_PV(pThis);
    2171 #endif
     2141    for (int i = 0; i < VBOX_DSOUND_MAX_EVENTS; i++)
     2142    {
     2143        if (pThis->aEvents[i])
     2144            CloseHandle(pThis->aEvents[i]);
     2145    }
    21722146
    21732147    LogFlowFuncLeave();
     
    21922166        IDirectSound_Release(pDirectSound);
    21932167
    2194 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    2195         /* Create notification event. */
    2196         pThis->aEvents[DSOUNDEVENT_NOTIFY] = CreateEvent(NULL /* Security attribute */,
    2197                                                          FALSE /* bManualReset */, FALSE /* bInitialState */,
    2198                                                          NULL /* lpName */);
    2199         Assert(pThis->aEvents[DSOUNDEVENT_NOTIFY] != NULL);
     2168        /* Create notification events. */
     2169        for (int i = 0; i < VBOX_DSOUND_MAX_EVENTS; i++)
     2170        {
     2171            pThis->aEvents[i] = CreateEvent(NULL /* Security attribute */,
     2172                                            FALSE /* bManualReset */, FALSE /* bInitialState */,
     2173                                            NULL /* lpName */);
     2174            Assert(pThis->aEvents[i] != NULL);
     2175        }
    22002176
    22012177        /* Start notification thread. */
    2202         rc = RTThreadCreate(&pThis->Thread, dsoundNotificationThread,
     2178        rc = RTThreadCreate(&pThis->Thread, dsoundThread,
    22032179                            pThis /*pvUser*/, 0 /*cbStack*/,
    22042180                            RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "dsoundNtfy");
     
    22102186                DSLOGREL(("DSound: Waiting for thread to initialize failed with rc=%Rrc\n", rc));
    22112187        }
    2212     else
     2188        else
    22132189            DSLOGREL(("DSound: Creating thread failed with rc=%Rrc\n", rc));
    2214 #else
    2215         rc = VINF_SUCCESS;
    2216 #endif
    22172190
    22182191        dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */);
     
    22522225static int dsoundConfigInit(PDRVHOSTDSOUND pThis, PCFGMNODE pCfg)
    22532226{
    2254     unsigned int uBufsizeOut, uBufsizeIn;
    2255 
    2256     CFGMR3QueryUIntDef(pCfg, "BufsizeOut", &uBufsizeOut, _16K);
    2257     CFGMR3QueryUIntDef(pCfg, "BufsizeIn",  &uBufsizeIn,  _16K);
    2258     pThis->cfg.cbBufferOut = uBufsizeOut;
    2259     pThis->cfg.cbBufferIn  = uBufsizeIn;
    2260 
    2261     pThis->cfg.pGuidPlay    = dsoundConfigQueryGUID(pCfg, "DeviceGuidOut", &pThis->cfg.uuidPlay);
    2262     pThis->cfg.pGuidCapture = dsoundConfigQueryGUID(pCfg, "DeviceGuidIn",  &pThis->cfg.uuidCapture);
    2263 
    2264     DSLOG(("DSound: Configuration cbBufferIn=%ld, cbBufferOut=%ld, DeviceGuidOut {%RTuuid}, DeviceGuidIn {%RTuuid}\n",
    2265            pThis->cfg.cbBufferIn,
    2266            pThis->cfg.cbBufferOut,
    2267            &pThis->cfg.uuidPlay,
    2268            &pThis->cfg.uuidCapture));
     2227    CFGMR3QueryUIntDef(pCfg, "LatencyMsIn",  &pThis->Cfg.msLatencyIn,  DRV_DSOUND_DEFAULT_LATENCY_MS_IN);
     2228    CFGMR3QueryUIntDef(pCfg, "LatencyMsOut", &pThis->Cfg.msLatencyOut, DRV_DSOUND_DEFAULT_LATENCY_MS_OUT);
     2229
     2230    pThis->Cfg.pGuidPlay    = dsoundConfigQueryGUID(pCfg, "DeviceGuidOut", &pThis->Cfg.uuidPlay);
     2231    pThis->Cfg.pGuidCapture = dsoundConfigQueryGUID(pCfg, "DeviceGuidIn",  &pThis->Cfg.uuidCapture);
     2232
     2233    DSLOG(("DSound: Configuration: Input latency = %ums, Output latency = %ums, DeviceGuidOut {%RTuuid}, DeviceGuidIn {%RTuuid}\n",
     2234           pThis->Cfg.msLatencyIn,
     2235           pThis->Cfg.msLatencyOut,
     2236           &pThis->Cfg.uuidPlay,
     2237           &pThis->Cfg.uuidCapture));
    22692238
    22702239    return VINF_SUCCESS;
     
    23952364    AssertPtrReturn(pStream,    PDMAUDIOSTREAMSTS_FLAG_NONE);
    23962365
    2397     PDRVHOSTDSOUND pThis     = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    23982366    PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
    23992367
    24002368    if (pStreamDS->fEnabled)
    2401     {
    2402         DWORD cbFree;
    2403         int rc = dsoundGetFreeOut(pThis, pStreamDS, &cbFree);
    2404         if (   RT_SUCCESS(rc)
    2405             && cbFree)
    2406         {
    2407             Log3Func(("cbFree=%ld\n", cbFree));
    2408             return (uint32_t)cbFree;
    2409         }
    2410     }
     2369        return (uint32_t)RTCircBufFree(pStreamDS->Out.pCircBuf);
    24112370
    24122371    return 0;
     
    24222381    AssertPtrReturn(pStream, 0);
    24232382
    2424     PDRVHOSTDSOUND pThis     = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    24252383    PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
    24262384
    24272385    if (pStreamDS->pCfg->enmDir == PDMAUDIODIR_OUT)
    24282386    {
    2429         DWORD dwStatus;
    2430         HRESULT hr = directSoundPlayGetStatus(pThis, pStreamDS->Out.pDSB, &dwStatus);
    2431         if (hr != DS_OK)
    2432             return 0;
    2433 
    2434          if (!(dwStatus & DSBSTATUS_PLAYING))
    2435             return 0;
    2436 
    2437          DWORD offPlayCursor, offWriteCursor;
    2438          hr = IDirectSoundBuffer8_GetCurrentPosition(pStreamDS->Out.pDSB, &offPlayCursor, &offWriteCursor);
    2439          if (SUCCEEDED(hr))
    2440          {
    2441              uint32_t cbPending;
    2442              if (pStreamDS->Out.offPlayCursorLastPending <= offPlayCursor)
    2443                  cbPending = offPlayCursor - pStreamDS->Out.offPlayCursorLastPending;
    2444              else
    2445                  cbPending = pStreamDS->Out.cbBufSize - pStreamDS->Out.offPlayCursorLastPending + offPlayCursor;
    2446 
    2447              pStreamDS->Out.cbWritten                -= RT_MIN(pStreamDS->Out.cbWritten, cbPending);
    2448              pStreamDS->Out.offPlayCursorLastPending  = offPlayCursor;
    2449 
    2450             LogFunc(("offPlayCursor=%RU32, offWriteCursor=%RU32\n", offPlayCursor, offWriteCursor));
    2451             LogFunc(("offPlayWritePos=%RU32, cbWritten=%RU64, cbPending=%RU32\n",
    2452                      pStreamDS->Out.offWritePos, pStreamDS->Out.cbWritten, cbPending));
    2453 
    2454             /*
    2455              * As we operate a DirectSound secondary *streaming* buffer which loops over
    2456              * the data repeatedly until stopped, we have to make at least an estimate when we're actually
    2457              * done playing the written data on the host.
    2458              */
    2459             return pStreamDS->Out.cbWritten;
    2460         }
    2461         else
    2462             LogFunc(("Failed with %Rhrc\n", hr));
     2387        uint32_t cbPending = 0;
     2388
     2389        /* Any uncommitted data left? */
     2390        if (pStreamDS->Out.pCircBuf)
     2391            cbPending = (uint32_t)RTCircBufUsed(pStreamDS->Out.pCircBuf);
     2392
     2393        /* Check if we have committed data which still needs to be played by
     2394         * by DirectSound's streaming buffer. */
     2395        if (!cbPending)
     2396        {
     2397            const uint64_t tsNowMs = RTTimeMilliTS();
     2398            if (pStreamDS->Out.tsLastPlayMs == 0)
     2399                pStreamDS->Out.tsLastPlayMs = tsNowMs;
     2400
     2401            const uint64_t diffLastPlayMs = tsNowMs - pStreamDS->Out.tsLastPlayMs;
     2402            const uint64_t msThreshold    = 100;
     2403
     2404            Log3Func(("diffLastPlayMs=%RU64ms\n", diffLastPlayMs));
     2405
     2406            cbPending = (diffLastPlayMs >= msThreshold) ? 0 : 1;
     2407
     2408            //if (!cbPending)
     2409            //    directSoundPlayStop(pThis, pStreamDS, false /* fFlush */);
     2410        }
     2411
     2412        return cbPending;
    24632413    }
    24642414    /* Note: For input streams we never have pending data left. */
     
    25042454    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    25052455    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    2506 
    2507     LogFlowFuncEnter();
    25082456
    25092457    /* Nothing to do here for DSound. */
     
    26412589#ifdef VBOX_WITH_AUDIO_CALLBACKS
    26422590    /* This backend supports host audio callbacks. */
    2643     pThis->IHostAudio.pfnSetCallback       = drvHostDSoundSetCallback;
     2591    pThis->IHostAudio.pfnSetCallback = drvHostDSoundSetCallback;
    26442592    pThis->pfnCallback               = NULL;
    2645 #endif
    2646 
    2647 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    2648     /*
    2649      * Get the IAudioConnector interface of the above driver/device.
    2650      */
    2651     pThis->pUpIAudioConnector = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
    2652     if (!pThis->pUpIAudioConnector)
    2653     {
    2654         AssertMsgFailed(("Configuration error: No audio connector interface above!\n"));
    2655         return VERR_PDM_MISSING_INTERFACE_ABOVE;
    2656     }
    26572593#endif
    26582594
     
    26652601    pThis->fEnabledIn  = false;
    26662602    pThis->fEnabledOut = false;
    2667 #ifdef VBOX_WITH_AUDIO_DSOUND_NOTIFICATIONS
    26682603    pThis->fStopped    = false;
    26692604    pThis->fShutdown   = false;
    26702605
    26712606    RT_ZERO(pThis->aEvents);
    2672     pThis->cEvents = 0;
    2673 #endif
    26742607
    26752608    int rc = VINF_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette