Index: /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp	(revision 73562)
+++ /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp	(revision 73563)
@@ -168,8 +168,10 @@
         } Out;
     };
+#ifdef LOG_ENABLED
     struct
     {
         uint64_t tsLastTransferredMs;
     } Dbg;
+#endif
 } DSOUNDSTREAM, *PDSOUNDSTREAM;
 
@@ -249,4 +251,6 @@
 static int      dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg);
 
+static int      dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable);
+static void     dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS);
 static void     dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis);
 static void     dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum);
@@ -808,12 +812,11 @@
  * @return  IPRT status code.
  * @param   pThis               Host audio driver instance.
- */
-static int dsoundPlayTransfer(PDRVHOSTDSOUND pThis)
-{
-    PDSOUNDSTREAM pStreamDS = pThis->pDSStrmOut;
-
-    if (   !pStreamDS
-        || !pStreamDS->fEnabled)
-    {
+ * @param   pStreamDS           Stream to transfer playback data for.
+ */
+static int dsoundPlayTransfer(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
+{
+    if (!pStreamDS->fEnabled)
+    {
+        Log2Func(("Stream disabled, skipping\n"));
         return VINF_SUCCESS;
     }
@@ -855,6 +858,8 @@
     if (!pStreamDS->Dbg.tsLastTransferredMs)
         pStreamDS->Dbg.tsLastTransferredMs = RTTimeMilliTS();
-    Log3Func(("tsLastTransferredMs=%RU64ms, cbAvail=%RU32, cbFree=%RU32 -> cbToTransfer=%RU32 (fDrain=%RTbool)\n",
-              RTTimeMilliTS() - pStreamDS->Dbg.tsLastTransferredMs, cbAvail, cbFree, cbToTransfer, pStreamDS->Out.fDrain));
+    Log3Func(("offPlay=%RU32, offWrite=%RU32, tsLastTransferredMs=%RU64ms, cbAvail=%RU32, cbFree=%RU32 -> cbToTransfer=%RU32 "
+              "(fFirst=%RTbool, fDrain=%RTbool)\n",
+              offPlayCursor, offWriteCursor, RTTimeMilliTS() - pStreamDS->Dbg.tsLastTransferredMs, cbAvail, cbFree, cbToTransfer,
+              pStreamDS->Out.fFirstTransfer, pStreamDS->Out.fDrain));
     pStreamDS->Dbg.tsLastTransferredMs = RTTimeMilliTS();
 #endif
@@ -915,5 +920,4 @@
         if (SUCCEEDED(hr))
         {
-            DSLOG(("DSound: Started playing output\n"));
             pStreamDS->Out.fFirstTransfer = false;
         }
@@ -977,17 +981,11 @@
     if (pStreamDS->Out.pDSB)
     {
-        if (pStreamDS->fEnabled)
-        {
-            DSLOG(("DSound: %s playback\n", fFlush ? "Stopping" : "Pausing"));
-
-            hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
+        DSLOG(("DSound: Stopping playback\n"));
+        hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
+        if (FAILED(hr))
+        {
+            hr = directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
             if (FAILED(hr))
-            {
-                hr = directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
-                if (FAILED(hr))
-                    hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
-            }
-
-            pStreamDS->fEnabled = false;
+                hr = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
         }
     }
@@ -995,9 +993,6 @@
     if (SUCCEEDED(hr))
     {
-        if (   fFlush
-            && pStreamDS->pCircBuf)
-        {
-            RTCircBufReset(pStreamDS->pCircBuf);
-        }
+        if (fFlush)
+            dsoundStreamReset(pThis, pStreamDS);
     }
 
@@ -1008,26 +1003,51 @@
 }
 
+/**
+ * Enables or disables a stream.
+ *
+ * @return  IPRT status code.
+ * @param   pThis               Host audio driver instance.
+ * @param   pStreamDS           Stream to enable / disable.
+ * @param   fEnable             Whether to enable or disable the stream.
+ */
+static int dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable)
+{
+    RT_NOREF(pThis);
+
+    LogFunc(("%s %s\n",
+             fEnable ? "Enabling" : "Disabling",
+             pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN ? "capture" : "playback"));
+
+    pStreamDS->fEnabled = fEnable;
+
+    return VINF_SUCCESS;
+}
+
 
 /**
  * Resets the state of a DirectSound stream.
  *
- * @return  HRESULT
  * @param   pThis               Host audio driver instance.
  * @param   pStreamDS           Stream to reset state for.
  */
-static HRESULT directSoundPlayReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
-{
-    AssertPtrReturn(pThis,     E_POINTER);
-    AssertPtrReturn(pStreamDS, E_POINTER);
-
-    Assert(pStreamDS->fEnabled == false);
-
-    pStreamDS->fEnabled           = true;
-    /* Note: Playing back via DirectSound starts in the notification thread
-     *       once enough audio output data is available. */
-
-    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT)
+static void dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
+{
+    RT_NOREF(pThis);
+
+    LogFunc(("Resetting %s\n",
+             pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN ? "capture" : "playback"));
+
+    if (pStreamDS->pCircBuf)
+        RTCircBufReset(pStreamDS->pCircBuf);
+
+    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
+    {
+        pStreamDS->In.offReadPos = 0;
+        pStreamDS->In.cOverruns  = 0;
+    }
+    else if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT)
     {
         pStreamDS->Out.fFirstTransfer = true;
+        pStreamDS->Out.fDrain         = false;
         pStreamDS->Out.cUnderruns     = 0;
 
@@ -1038,9 +1058,14 @@
         pStreamDS->Out.cbWritten = 0;
 
+        pStreamDS->Out.offWritePos = 0;
         pStreamDS->Out.offPlayCursorLastPending = 0;
         pStreamDS->Out.offPlayCursorLastPlayed = 0;
     }
-
-    return S_OK;
+    else
+        AssertFailed();
+
+#ifdef LOG_ENABLED
+    pStreamDS->Dbg.tsLastTransferredMs = 0;
+#endif
 }
 
@@ -1061,4 +1086,5 @@
     for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     {
+        DSLOG(("DSound: Starting playback\n"));
         hr = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, fFlags);
         if (   SUCCEEDED(hr)
@@ -1158,9 +1184,9 @@
  * @return  IPRT status code.
  * @param   pThis               Host audio driver instance.
- */
-static int dsoundCaptureTransfer(PDRVHOSTDSOUND pThis)
-{
-    PDSOUNDSTREAM pStreamDS = pThis->pDSStrmIn;
-    AssertPtr(pStreamDS);
+ * @param   pStreamDS           Stream to capture audio data for.
+ */
+static int dsoundCaptureTransfer(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
+{
+    RT_NOREF(pThis);
 
     LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pStreamDS->In.pDSCB;
@@ -1170,5 +1196,8 @@
     HRESULT hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pDSCB, NULL, &offCaptureCursor);
     if (FAILED(hr))
+    {
+        AssertFailed();
         return VERR_ACCESS_DENIED; /** @todo Find a better rc. */
+    }
 
     DWORD cbUsed = dsoundRingDistance(offCaptureCursor, pStreamDS->In.offReadPos, pStreamDS->cbBufSize);
@@ -1473,21 +1502,12 @@
     if (pStreamDS->In.pDSCB)
     {
-        if (pStreamDS->fEnabled)
-        {
-            DSLOG(("DSound: Stopping capture\n"));
-
-            hr = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
-            if (SUCCEEDED(hr))
-                pStreamDS->fEnabled = false;
-        }
+        DSLOG(("DSound: Stopping capture\n"));
+        hr = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
     }
 
     if (SUCCEEDED(hr))
     {
-        if (   fFlush
-            && pStreamDS->pCircBuf)
-        {
-            RTCircBufReset(pStreamDS->pCircBuf);
-        }
+        if (fFlush)
+             dsoundStreamReset(pThis, pStreamDS);
     }
 
@@ -1503,8 +1523,6 @@
     AssertPtrReturn(pStreamDS, E_POINTER);
 
-    Assert(pStreamDS->fEnabled == false);
-
     HRESULT hr;
-    if (pStreamDS->In.pDSCB != NULL)
+    if (pStreamDS->In.pDSCB)
     {
         DWORD dwStatus;
@@ -1526,12 +1544,5 @@
                 DSLOG(("DSound: Starting to capture\n"));
                 hr = IDirectSoundCaptureBuffer8_Start(pStreamDS->In.pDSCB, fFlags);
-                if (SUCCEEDED(hr))
-                {
-                    pStreamDS->fEnabled = true;
-
-                    pStreamDS->In.offReadPos = 0;
-                    pStreamDS->In.cOverruns  = 0;
-                }
-                else
+                if (FAILED(hr))
                     DSLOGREL(("DSound: Starting to capture failed with %Rhrc\n", hr));
             }
@@ -1753,22 +1764,15 @@
     LogFlowFunc(("pStreamDS=%p, pCfgReq=%p\n", pStreamDS, pCfgReq));
 
-    pStreamDS->cbBufSize = 0;
-
-    pStreamDS->Out.pDSB = NULL;
-    pStreamDS->Out.offWritePos = 0;
-    pStreamDS->Out.offPlayCursorLastPlayed = 0;
-    pStreamDS->Out.offPlayCursorLastPending = 0;
-    pStreamDS->Out.cbWritten = 0;
-    pStreamDS->Out.cbTransferred = 0;
-    pStreamDS->Out.fFirstTransfer = true;
-    pStreamDS->Out.fDrain = false;
-    pStreamDS->Out.cbLastTransferred = 0;
-    pStreamDS->Out.tsLastTransferred = 0;
-
     int rc = VINF_SUCCESS;
 
     /* Try to open playback in case the device is already there. */
     HRESULT hr = directSoundPlayOpen(pThis, pStreamDS, pCfgReq, pCfgAcq);
-    if (FAILED(hr))
+    if (SUCCEEDED(hr))
+    {
+        rc = DrvAudioHlpStreamCfgCopy(&pStreamDS->Cfg, pCfgAcq);
+        if (RT_SUCCESS(rc))
+            dsoundStreamReset(pThis, pStreamDS);
+    }
+    else
         rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
 
@@ -1788,7 +1792,5 @@
         case PDMAUDIOSTREAMCMD_ENABLE:
         {
-            hr = directSoundPlayReset(pThis, pStreamDS);
-            if (FAILED(hr))
-                rc = VERR_NOT_SUPPORTED; /** @todo Fix this. */
+            dsoundStreamEnable(pThis, pStreamDS, true /* fEnable */);
             break;
         }
@@ -1803,7 +1805,7 @@
 
         case PDMAUDIOSTREAMCMD_DISABLE:
-        case PDMAUDIOSTREAMCMD_PAUSE:
-        {
-            hr = directSoundPlayStop(pThis, pStreamDS, enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE /* fFlush */);
+        {
+            dsoundStreamEnable(pThis, pStreamDS, false /* fEnable */);
+            hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
             if (FAILED(hr))
                 rc = VERR_NOT_SUPPORTED;
@@ -1811,9 +1813,18 @@
         }
 
+        case PDMAUDIOSTREAMCMD_PAUSE:
+        {
+            hr = directSoundPlayStop(pThis, pStreamDS, false /* fFlush */);
+            if (FAILED(hr))
+                rc = VERR_NOT_SUPPORTED;
+            break;
+        }
+
         case PDMAUDIOSTREAMCMD_DRAIN:
         {
             /* Make sure we transferred everything. */
+            pStreamDS->fEnabled = true;
             pStreamDS->Out.fDrain = true;
-            rc = dsoundPlayTransfer(pThis);
+            rc = dsoundPlayTransfer(pThis, pStreamDS);
             if (   RT_SUCCESS(rc)
                 && pStreamDS->Out.fFirstTransfer)
@@ -1890,5 +1901,5 @@
     pStreamDS->Out.cbWritten += cbWrittenTotal;
 
-    rc = dsoundPlayTransfer(pThis);
+    rc = dsoundPlayTransfer(pThis, pStreamDS);
     AssertRC(rc);
 
@@ -1927,16 +1938,15 @@
              pStreamDS, pCfgReq, DrvAudioHlpRecSrcToStr(pCfgReq->DestSource.Source)));
 
-    /* Init the stream structure and save relevant information to it. */
-    pStreamDS->cbBufSize     = 0;
-
-    pStreamDS->In.pDSCB      = NULL;
-    pStreamDS->In.offReadPos = 0;
-    pStreamDS->In.cOverruns  = 0;
-
     int rc = VINF_SUCCESS;
 
     /* Try to open capture in case the device is already there. */
     HRESULT hr = directSoundCaptureOpen(pThis, pStreamDS, pCfgReq, pCfgAcq);
-    if (FAILED(hr))
+    if (SUCCEEDED(hr))
+    {
+        rc = DrvAudioHlpStreamCfgCopy(&pStreamDS->Cfg, pCfgAcq);
+        if (RT_SUCCESS(rc))
+            dsoundStreamReset(pThis, pStreamDS);
+    }
+    else
         rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
 
@@ -1954,4 +1964,6 @@
     {
         case PDMAUDIOSTREAMCMD_ENABLE:
+            dsoundStreamEnable(pThis, pStreamDS, true /* fEnable */);
+            RT_FALL_THROUGH();
         case PDMAUDIOSTREAMCMD_RESUME:
         {
@@ -1984,8 +1996,8 @@
 
         case PDMAUDIOSTREAMCMD_DISABLE:
+            dsoundStreamEnable(pThis, pStreamDS, false /* fEnable */);
+            RT_FALL_THROUGH();
         case PDMAUDIOSTREAMCMD_PAUSE:
         {
-            AssertPtr(pThis->pDSC);
-
             directSoundCaptureStop(pThis, pStreamDS,
                                    enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE /* fFlush */);
@@ -2331,14 +2343,7 @@
 
     PDMAUDIOSTREAMSTS strmSts = PDMAUDIOSTREAMSTS_FLAG_INITIALIZED;
-    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
-    {
-        if (pStreamDS->fEnabled)
-            strmSts |= PDMAUDIOSTREAMSTS_FLAG_ENABLED;
-    }
-    else
-    {
-        if (pStreamDS->fEnabled)
-            strmSts |= PDMAUDIOSTREAMSTS_FLAG_ENABLED;
-    }
+
+    if (pStreamDS->fEnabled)
+        strmSts |= PDMAUDIOSTREAMSTS_FLAG_ENABLED;
 
     return strmSts;
@@ -2357,5 +2362,5 @@
 
     if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
-        return dsoundCaptureTransfer(pThis);
+        return dsoundCaptureTransfer(pThis, pStreamDS);
 
     return VINF_SUCCESS;
