Index: /trunk/src/VBox/Devices/Audio/DrvAudio.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 58743)
+++ /trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 58744)
@@ -1394,4 +1394,119 @@
 }
 
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+static PPDMAUDIOCALLBACK drvAudioCallbackDuplicate(PPDMAUDIOCALLBACK pCB)
+{
+    PPDMAUDIOCALLBACK pCBCopy = (PPDMAUDIOCALLBACK)RTMemDup((void *)pCB, sizeof(PDMAUDIOCALLBACK));
+    if (!pCBCopy)
+        return NULL;
+
+    if (pCB->pvCtx)
+    {
+        pCBCopy->pvCtx = RTMemDup(pCB->pvCtx, pCB->cbCtx);
+        if (!pCBCopy->pvCtx)
+        {
+            RTMemFree(pCBCopy);
+            return NULL;
+        }
+
+        pCBCopy->cbCtx = pCB->cbCtx;
+    }
+
+    return pCBCopy;
+}
+
+static void drvAudioCallbackDestroy(PPDMAUDIOCALLBACK pCB)
+{
+    if (!pCB)
+        return;
+
+    RTListNodeRemove(&pCB->Node);
+    if (pCB->pvCtx)
+    {
+        Assert(pCB->cbCtx);
+        RTMemFree(pCB->pvCtx);
+    }
+    RTMemFree(pCB);
+}
+
+static DECLCALLBACK(int) drvAudioRegisterCallbacks(PPDMIAUDIOCONNECTOR pInterface,
+                                                   PPDMAUDIOCALLBACK paCallbacks, size_t cCallbacks)
+{
+    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
+    AssertPtrReturn(paCallbacks, VERR_INVALID_POINTER);
+    AssertReturn(cCallbacks,     VERR_INVALID_PARAMETER);
+
+    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+    int          rc = VINF_SUCCESS;
+
+    for (size_t i = 0; i < cCallbacks; i++)
+    {
+        PPDMAUDIOCALLBACK pCB = drvAudioCallbackDuplicate(&paCallbacks[i]);
+        if (!pCB)
+        {
+            rc = VERR_NO_MEMORY;
+            break;
+        }
+
+        switch (pCB->enmType)
+        {
+            case PDMAUDIOCALLBACKTYPE_INPUT:
+                RTListAppend(&pThis->lstCBIn, &pCB->Node);
+                break;
+
+            case PDMAUDIOCALLBACKTYPE_OUTPUT:
+                RTListAppend(&pThis->lstCBOut, &pCB->Node);
+                break;
+
+            default:
+                AssertMsgFailed(("Not supported\n"));
+                break;
+        }
+    }
+
+    /** @todo Undo allocations on error. */
+
+    return rc;
+}
+
+static DECLCALLBACK(int) drvAudioCallback(PPDMIAUDIOCONNECTOR pInterface, PDMAUDIOCALLBACKTYPE enmType,
+                                          void *pvUser, size_t cbUser)
+{
+    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
+    AssertPtrReturn(pvUser,     VERR_INVALID_POINTER);
+    AssertReturn(cbUser,        VERR_INVALID_PARAMETER);
+
+    PDRVAUDIO     pThis       = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+    PRTLISTANCHOR pListAnchor = NULL;
+
+    switch (enmType)
+    {
+        case PDMAUDIOCALLBACKTYPE_INPUT:
+            pListAnchor = &pThis->lstCBIn;
+            break;
+
+        case PDMAUDIOCALLBACKTYPE_OUTPUT:
+            pListAnchor = &pThis->lstCBOut;
+            break;
+
+        default:
+            AssertMsgFailed(("Not supported\n"));
+            break;
+    }
+
+    if (pListAnchor)
+    {
+        PPDMAUDIOCALLBACK pCB;
+        RTListForEach(pListAnchor, pCB, PDMAUDIOCALLBACK, Node)
+        {
+            Assert(pCB->enmType == enmType);
+            pCB->pfnCallback(enmType, pCB->pvCtx, pCB->cbCtx, pvUser, cbUser);
+        }
+    }
+
+    return VINF_SUCCESS;
+}
+#endif
+
 static int drvAudioHostInit(PCFGMNODE pCfgHandle, PDRVAUDIO pThis)
 {
@@ -1530,4 +1645,8 @@
     RTListInit(&pThis->lstHstStrmIn);
     RTListInit(&pThis->lstHstStrmOut);
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    RTListInit(&pThis->lstCBIn);
+    RTListInit(&pThis->lstCBOut);
+#endif
 
     int rc = VINF_SUCCESS;
@@ -1965,4 +2084,13 @@
         pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
 
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    PPDMAUDIOCALLBACK pCB, pCBNext;
+    RTListForEachSafe(&pThis->lstCBIn, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
+        drvAudioCallbackDestroy(pCB);
+
+    RTListForEachSafe(&pThis->lstCBOut, pCB, pCBNext, PDMAUDIOCALLBACK, Node)
+        drvAudioCallbackDestroy(pCB);
+#endif
+
     LogFlowFuncLeave();
 }
@@ -1986,5 +2114,5 @@
     /* IBase. */
     pDrvIns->IBase.pfnQueryInterface                 = drvAudioQueryInterface;
-    /* IAudio. */
+    /* IAudioConnector. */
     pThis->IAudioConnector.pfnQueryStatus            = drvAudioQueryStatus;
     pThis->IAudioConnector.pfnRead                   = drvAudioRead;
@@ -2002,4 +2130,8 @@
     pThis->IAudioConnector.pfnCreateOut              = drvAudioCreateOut;
     pThis->IAudioConnector.pfnPlayOut                = drvAudioPlayOut;
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    pThis->IAudioConnector.pfnRegisterCallbacks      = drvAudioRegisterCallbacks;
+    pThis->IAudioConnector.pfnCallback               = drvAudioCallback;
+#endif
 
     /*
Index: /trunk/src/VBox/Devices/Audio/DrvAudio.h
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvAudio.h	(revision 58743)
+++ /trunk/src/VBox/Devices/Audio/DrvAudio.h	(revision 58744)
@@ -83,5 +83,5 @@
     /** Shutdown indicator. */
     bool                    fTerminate;
-    /** The audio interface presented to the device/driver above us. */
+    /** Our audio connector interface. */
     PDMIAUDIOCONNECTOR      IAudioConnector;
     /** Pointer to the driver instance. */
@@ -98,8 +98,12 @@
      *  from the backend. */
     PDMAUDIOBACKENDCFG      BackendCfg;
-
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    /** @todo Use a map with primary key set to the callback type? */
+    RTLISTANCHOR            lstCBIn;
+    RTLISTANCHOR            lstCBOut;
+#endif
 } DRVAUDIO, *PDRVAUDIO;
 
-/** Makes a PDRVBLOCK out of a PPDMIBLOCK. */
+/** Makes a PDRVAUDIO out of a PPDMIAUDIOCONNECTOR. */
 #define PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface) \
     ( (PDRVAUDIO)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIO, IAudioConnector)) )
Index: /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp	(revision 58743)
+++ /trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp	(revision 58744)
@@ -114,27 +114,29 @@
 {
     /** Pointer to the driver instance structure. */
-    PPDMDRVINS    pDrvIns;
-    /** Pointer to host audio interface. */
-    PDMIHOSTAUDIO IHostAudio;
+    PPDMDRVINS          pDrvIns;
+    /** Our audio host audio interface. */
+    PDMIHOSTAUDIO       IHostAudio;
     /** List of found host input devices. */
-    RTLISTANCHOR  lstDevInput;
+    RTLISTANCHOR        lstDevInput;
     /** List of found host output devices. */
-    RTLISTANCHOR  lstDevOutput;
+    RTLISTANCHOR        lstDevOutput;
     /** DirectSound configuration options. */
-    DSOUNDHOSTCFG cfg;
+    DSOUNDHOSTCFG       cfg;
 #ifdef VBOX_WITH_AUDIO_CALLBACKS
+    /** Pointer to the audio connector interface of the driver/device above us. */
+    PPDMIAUDIOCONNECTOR pUpIAudioConnector;
     /** Stopped indicator. */
-    bool          fStopped;
+    bool                fStopped;
     /** Shutdown indicator. */
-    bool          fShutdown;
+    bool                fShutdown;
     /** Notification thread. */
-    RTTHREAD      Thread;
+    RTTHREAD            Thread;
     /** Array of events to wait for in notification thread. */
-    HANDLE        aEvents[VBOX_DSOUND_MAX_EVENTS];
+    HANDLE              aEvents[VBOX_DSOUND_MAX_EVENTS];
     /** Number of events to wait for in notification thread.
      *  Must not exceed VBOX_DSOUND_MAX_EVENTS. */
-    uint8_t       cEvents;
-    PDSOUNDSTREAMIN pStrmIn;
-    PDSOUNDSTREAMOUT pStrmOut;
+    uint8_t             cEvents;
+    PDSOUNDSTREAMIN     pStrmIn;
+    PDSOUNDSTREAMOUT    pStrmOut;
 #endif
 } DRVHOSTDSOUND, *PDRVHOSTDSOUND;
@@ -429,4 +431,7 @@
             pThis->pStrmOut = NULL;
         }
+
+        int rc2 = dsoundNotifyThread(pThis, false /* fShutdown */);
+        AssertRC(rc2);
 #endif
         IDirectSoundBuffer8_Release(pDSoundStrmOut->pDSB);
@@ -1724,6 +1729,14 @@
                     DWORD cbPlayPos;
                     hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pThis->pStrmOut->pDSB, NULL, &cbPlayPos);
+                    if (SUCCEEDED(hr))
+                    {
                         LogFlowFunc(("Output: hr=%Rhrc, dwPlayPos=%ld\n", hr, cbPlayPos));
+
+                        uint32_t cbFree = pThis->pStrmOut->csPlaybackBufferSize - pThis->pStrmOut->cbPlayWritePos;
+
+                        AssertPtr(pThis->pUpIAudioConnector);
+                        pThis->pUpIAudioConnector->pfnCallback(pThis->pUpIAudioConnector, PDMAUDIOCALLBACKTYPE_OUTPUT, &cbFree, sizeof(cbFree));
                     }
+                }
                 break;
             }
@@ -1900,5 +1913,5 @@
 
     /*
-     * Init the static parts.
+     * Init basic data members and interfaces.
      */
     pThis->pDrvIns                   = pDrvIns;
@@ -1908,4 +1921,19 @@
     PDMAUDIO_IHOSTAUDIO_CALLBACKS(drvHostDSound);
 
+#ifdef VBOX_WITH_AUDIO_CALLBACKS
+    /*
+     * Get the IAudioConnector interface of the above driver/device.
+     */
+    pThis->pUpIAudioConnector = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
+    if (!pThis->pUpIAudioConnector)
+    {
+        AssertMsgFailed(("Configuration error: No audio connector interface above!\n"));
+        return VERR_PDM_MISSING_INTERFACE_ABOVE;
+    }
+#endif
+
+    /*
+     * Init the static parts.
+     */
     RTListInit(&pThis->lstDevInput);
     RTListInit(&pThis->lstDevOutput);
