Index: /trunk/src/VBox/Main/include/AudioDriver.h
===================================================================
--- /trunk/src/VBox/Main/include/AudioDriver.h	(revision 70562)
+++ /trunk/src/VBox/Main/include/AudioDriver.h	(revision 70563)
@@ -30,9 +30,7 @@
 struct AudioDriverCfg
 {
-    AudioDriverCfg(Utf8Str a_strDev = "", unsigned a_uInst = 0, unsigned a_uLUN = 0,
-                   Utf8Str a_strName = "")
+    AudioDriverCfg(Utf8Str a_strDev = "", unsigned a_uInst = 0, Utf8Str a_strName = "")
         : strDev(a_strDev)
         , uInst(a_uInst)
-        , uLUN(a_uLUN)
         , strName(a_strName) { }
 
@@ -41,5 +39,4 @@
         this->strDev  = that.strDev;
         this->uInst   = that.uInst;
-        this->uLUN    = that.uLUN;
         this->strName = that.strName;
 
@@ -51,7 +48,4 @@
     /** The device instance. */
     unsigned             uInst;
-    /** The LUN the driver is attached to.
-     *  Set the UINT8_MAX if not attached. */
-    unsigned             uLUN;
     /** The driver name. */
     Utf8Str              strName;
@@ -76,13 +70,15 @@
     Console *GetParent(void) { return mpConsole; }
 
+    int Initialize(AudioDriverCfg *pCfg);
+
     bool IsAttached(void) { return mfAttached; }
 
-    static DECLCALLBACK(int) Attach(AudioDriver *pThis, AudioDriverCfg *pCfg);
+    static DECLCALLBACK(int) Attach(AudioDriver *pThis);
 
     static DECLCALLBACK(int) Detach(AudioDriver *pThis);
 
-    int Configure(AudioDriverCfg *pCfg, bool fAttach);
+protected:
 
-protected:
+    int configure(unsigned uLUN, bool fAttach);
 
     /**
@@ -105,4 +101,7 @@
     /** Whether the driver is attached or not. */
     bool                 mfAttached;
+    /** The LUN the driver is attached to.
+     *  Set the UINT8_MAX if not attached. */
+    unsigned             muLUN;
 };
 
Index: /trunk/src/VBox/Main/include/DisplayImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 70562)
+++ /trunk/src/VBox/Main/include/DisplayImpl.h	(revision 70563)
@@ -212,8 +212,5 @@
     VIDEORECFEATURES         i_videoRecGetEnabled(void);
     bool                     i_videoRecStarted(void);
-# ifdef VBOX_WITH_AUDIO_VIDEOREC
-    int                      i_videoRecConfigureAudioDriver(const Utf8Str& strAdapter, unsigned uInstance, unsigned uLUN, bool fAttach);
-# endif
-    static DECLCALLBACK(int) i_videoRecConfigure(Display *pThis, PVIDEORECCFG pCfg, bool fAttachDetach, unsigned *puLUN);
+    void                     i_videoRecInvalidate();
     int                      i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs);
     int                      i_videoRecStart(void);
Index: /trunk/src/VBox/Main/include/DrvAudioVideoRec.h
===================================================================
--- /trunk/src/VBox/Main/include/DrvAudioVideoRec.h	(revision 70562)
+++ /trunk/src/VBox/Main/include/DrvAudioVideoRec.h	(revision 70563)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2017 Oracle Corporation
+ * Copyright (C) 2017-2018 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -23,7 +23,11 @@
 #include <VBox/vmm/pdmifs.h>
 
+#include "AudioDriver.h"
+
+using namespace com;
+
 class Console;
 
-class AudioVideoRec
+class AudioVideoRec : public AudioDriver
 {
 
@@ -37,6 +41,4 @@
     static const PDMDRVREG DrvReg;
 
-    Console *getParent(void) { return mpConsole; }
-
 public:
 
@@ -48,8 +50,8 @@
 private:
 
+    void configureDriver(PCFGMNODE pLunCfg);
+
     /** Pointer to the associated video recording audio driver. */
     struct DRVAUDIOVIDEOREC *mpDrv;
-    /** Pointer to parent. */
-    Console * const          mpConsole;
 };
 
Index: /trunk/src/VBox/Main/src-client/AudioDriver.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/AudioDriver.cpp	(revision 70562)
+++ /trunk/src/VBox/Main/src-client/AudioDriver.cpp	(revision 70563)
@@ -35,4 +35,5 @@
     : mpConsole(pConsole)
     , mfAttached(false)
+    , muLUN(UINT8_MAX)
 {
 }
@@ -58,5 +59,4 @@
     unsigned uLUN = 0;
 
-    /* First check if the LUN already exists. */
     PCFGMNODE pDevLUN;
     for (;;)
@@ -71,4 +71,14 @@
 }
 
+int AudioDriver::Initialize(AudioDriverCfg *pCfg)
+{
+    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
+
+    /* Apply configuration. */
+    mCfg = *pCfg;
+
+    return VINF_SUCCESS;
+}
+
 /**
  * Configures the audio driver (to CFGM) and attaches it to the audio chain.
@@ -77,8 +87,7 @@
  * @returns IPRT status code.
  * @param   pThis               Audio driver to detach.
- * @param   pCfg                Audio driver configuration to use for the audio driver to attach.
  */
 /* static */
-DECLCALLBACK(int) AudioDriver::Attach(AudioDriver *pThis, AudioDriverCfg *pCfg)
+DECLCALLBACK(int) AudioDriver::Attach(AudioDriver *pThis)
 {
     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
@@ -90,19 +99,28 @@
 
     if (pThis->mfAttached) /* Already attached? Bail out. */
+    {
+        LogFunc(("%s: Already attached\n", pThis->mCfg.strName.c_str()));
         return VINF_SUCCESS;
-
-    if (pCfg->uLUN == UINT8_MAX) /* No LUN assigned / configured yet? Retrieve it. */
-        pCfg->uLUN = pThis->getFreeLUN();
+    }
+
+    AudioDriverCfg *pCfg = &pThis->mCfg;
+
+    unsigned uLUN = pThis->muLUN;
+    if (uLUN == UINT8_MAX) /* No LUN assigned / configured yet? Retrieve it. */
+        uLUN = pThis->getFreeLUN();
 
     LogFunc(("strName=%s, strDevice=%s, uInst=%u, uLUN=%u\n",
-             pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN));
-
-    vrc = pThis->Configure(pCfg, true /* Attach */);
-    if (RT_SUCCESS(vrc))
-        vrc = PDMR3DriverAttach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN, 0 /* fFlags */, NULL /* ppBase */);
-
-    if (RT_SUCCESS(vrc))
-    {
+             pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, uLUN));
+
+    vrc = pThis->configure(uLUN, true /* Attach */);
+    if (RT_SUCCESS(vrc))
+        vrc = PDMR3DeviceAttach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, uLUN, 0 /* fFlags */,
+                                NULL /* ppBase */);
+    if (RT_SUCCESS(vrc))
+    {
+        pThis->muLUN      = uLUN;
         pThis->mfAttached = true;
+
+        LogRel2(("%s: Driver attached (LUN #%u)\n", pCfg->strName.c_str(), pThis->muLUN));
     }
     else
@@ -124,9 +142,14 @@
     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
 
+    if (!pThis->mfAttached) /* Not attached? Bail out. */
+    {
+        LogFunc(("%s: Not attached\n", pThis->mCfg.strName.c_str()));
+        return VINF_SUCCESS;
+    }
+
     Console::SafeVMPtrQuiet ptrVM(pThis->mpConsole);
     Assert(ptrVM.isOk());
 
-    if (!pThis->mfAttached) /* Not attached? Bail out. */
-        return VINF_SUCCESS;
+    Assert(pThis->muLUN != UINT8_MAX);
 
     int vrc = VINF_SUCCESS;
@@ -135,16 +158,17 @@
 
     LogFunc(("strName=%s, strDevice=%s, uInst=%u, uLUN=%u\n",
-             pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN));
-
-    vrc = PDMR3DriverDetach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN, "AUDIO",
+             pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, pThis->muLUN));
+
+    vrc = PDMR3DriverDetach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pThis->muLUN, "AUDIO",
                             0 /* iOccurrence */, 0 /* fFlags */);
     if (RT_SUCCESS(vrc))
-        vrc = pThis->Configure(pCfg, false /* Detach */);
-
-    if (RT_SUCCESS(vrc))
-    {
-        pCfg->uLUN = UINT8_MAX;
-
+        vrc = pThis->configure(pThis->muLUN, false /* Detach */);
+
+    if (RT_SUCCESS(vrc))
+    {
+        pThis->muLUN      = UINT8_MAX;
         pThis->mfAttached = false;
+
+        LogRel2(("%s: Driver detached\n", pCfg->strName.c_str()));
     }
     else
@@ -158,21 +182,15 @@
  *
  * @returns VBox status code.
- * @param   pCfg                Audio driver configuration to use.
+ * @param   uLUN                LUN to attach driver to.
  * @param   fAttach             Whether to attach or detach the driver configuration to CFGM.
  *
  * @thread EMT
  */
-int AudioDriver::Configure(AudioDriverCfg *pCfg, bool fAttach)
-{
-    if (pCfg->strDev.isEmpty()) /* No audio device configured. Bail out. */
-        return VINF_SUCCESS;
-
+int AudioDriver::configure(unsigned uLUN, bool fAttach)
+{
     int rc = VINF_SUCCESS;
 
     Console::SafeVMPtrQuiet ptrVM(mpConsole);
     Assert(ptrVM.isOk());
-
-    /* Apply configuration. */
-    mCfg = *pCfg;
 
     PUVM pUVM = ptrVM.rawUVM();
@@ -184,14 +202,16 @@
     AssertPtr(pDev0);
 
-    PCFGMNODE pDevLun = CFGMR3GetChildF(pDev0, "LUN#%u/", mCfg.uLUN);
+    PCFGMNODE pDevLun = CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN);
 
     if (fAttach)
     {
+        AssertMsg(uLUN != UINT8_MAX, ("%s: LUN is undefined when it must not\n", mCfg.strName.c_str()));
+
         if (!pDevLun)
         {
-            LogRel2(("%s: Configuring audio driver\n", mCfg.strName.c_str()));
+            LogRel2(("%s: Configuring audio driver (to LUN #%RU8)\n", mCfg.strName.c_str(), uLUN));
 
             PCFGMNODE pLunL0;
-            CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%RU8", mCfg.uLUN);
+            CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%RU8", uLUN);
             CFGMR3InsertString(pLunL0, "Driver", "AUDIO");
 
@@ -211,4 +231,6 @@
                 configureDriver(pLunCfg);
         }
+        else
+            rc = VERR_ALREADY_EXISTS;
     }
     else /* Detach */
@@ -219,7 +241,16 @@
             CFGMR3RemoveNode(pDevLun);
         }
-    }
-
-    AssertRC(rc);
+        else
+            rc = VERR_NOT_FOUND;
+    }
+
+#ifdef DEBUG_andy
+    CFGMR3Dump(pDev0);
+#endif
+
+    if (RT_FAILURE(rc))
+        LogRel(("%s: %s audio driver failed with rc=%Rrc\n",
+                mCfg.strName.c_str(), fAttach ? "Configuring" : "Unconfiguring", rc));
+
     return rc;
 }
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 70562)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 70563)
@@ -5405,15 +5405,5 @@
                             mConsoleVRDPServer->Stop();
 
-                            int vrc;
-#ifdef VBOX_WITH_AUDIO_VRDE
-                            if (!mAudioVRDE->IsAttached())
-                            {
-                                vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY /*idDstCpu*/,
-                                                       (PFNRT)AudioVRDE::Attach, 2,
-                                                       mAudioVRDE, mAudioVRDE->GetConfig());
-                                AssertRC(vrc);
-                            }
-#endif
-                            vrc = mConsoleVRDPServer->Launch();
+                            int vrc = mConsoleVRDPServer->Launch();
                             if (vrc != VINF_SUCCESS)
                             {
@@ -5422,5 +5412,23 @@
                             }
                             else
+                            {
+#ifdef VBOX_WITH_AUDIO_VRDE
+                                alock.acquire();
+
+                                PVMREQ pReq;
+                                int vrc2 = VMR3ReqCallU(mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                                        (PFNRT)AudioVRDE::Attach, 1, 
+                                                        mAudioVRDE);
+
+                                /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                                alock.release();
+
+                                if (vrc2 == VERR_TIMEOUT)
+                                    vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                                AssertRC(vrc2);
+                                VMR3ReqFree(pReq);
+#endif
                                 mConsoleVRDPServer->EnableConnections();
+                            }
                         }
                         else
@@ -5428,11 +5436,18 @@
                             mConsoleVRDPServer->Stop();
 #ifdef VBOX_WITH_AUDIO_VRDE
-                            if (mAudioVRDE->IsAttached())
-                            {
-                                int vrc2 = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY /*idDstCpu*/,
-                                                            (PFNRT)AudioVRDE::Detach, 1,
-                                                            mAudioVRDE);
-                                AssertRC(vrc2);
-                            }
+                            alock.acquire();
+
+                            PVMREQ pReq;
+                            int vrc2 = VMR3ReqCallU(mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                                    (PFNRT)AudioVRDE::Detach, 1, 
+                                                    mAudioVRDE);
+
+                            /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                            alock.release();
+
+                            if (vrc2 == VERR_TIMEOUT)
+                                vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                            AssertRC(vrc2);
+                            VMR3ReqFree(pReq);
 #endif
                         }
@@ -5529,32 +5544,54 @@
             AssertPtr(pDisplay);
 
-            /* Release lock because the call scheduled on EMT may also try to take it. */
-            alock.release();
-
-            const PVIDEORECCFG pCfg = pDisplay->i_videoRecGetConfig();
+            pDisplay->i_videoRecInvalidate();
+
+            int vrc;
+
+            if (!mDisplay->i_videoRecStarted())
+            {
 # ifdef VBOX_WITH_AUDIO_VIDEOREC
-            const unsigned     uLUN = pCfg->Audio.uLUN; /* Get the currently configured LUN. */
-# else
-            const unsigned     uLUN = 0;
+                /* Attach the video recording audio driver if required. */
+                if (mDisplay->i_videoRecGetEnabled() & VIDEORECFEATURE_AUDIO)
+                {
+                    PVMREQ pReq;
+                    int vrc2 = VMR3ReqCallU(mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                            (PFNRT)AudioVideoRec::Attach, 1, 
+                                            mAudioVideoRec);
+
+                    /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                    alock.release();
+
+                    if (vrc2 == VERR_TIMEOUT)
+                        vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                    AssertRC(vrc2);
+                    VMR3ReqFree(pReq);
+
+                    alock.acquire();
+                }
 # endif
-            int vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY /*idDstCpu*/,
-                                       (PFNRT)Display::i_videoRecConfigure, 4,
-                                       pDisplay, pCfg, true /* fAttachDetach */, &uLUN);
-            if (RT_SUCCESS(vrc))
-            {
-                /* Make sure to acquire the lock again after we're done running in EMT. */
-                alock.acquire();
-
-                if (!mDisplay->i_videoRecStarted())
-                {
-                    vrc = mDisplay->i_videoRecStart();
-                    if (RT_FAILURE(vrc))
-                        rc = setError(E_FAIL, tr("Unable to start video capturing (%Rrc)"), vrc);
-                }
-                else
-                    mDisplay->i_videoRecStop();
+                vrc = mDisplay->i_videoRecStart();
+                if (RT_FAILURE(vrc))
+                    rc = setError(E_FAIL, tr("Unable to start video capturing (%Rrc)"), vrc);
             }
             else
-                rc = setError(E_FAIL, tr("Unable to set screens for capturing (%Rrc)"), vrc);
+            {
+                mDisplay->i_videoRecStop();
+# ifdef VBOX_WITH_AUDIO_VIDEOREC
+                PVMREQ pReq;
+                int vrc2 = VMR3ReqCallU(mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                        (PFNRT)AudioVideoRec::Detach, 1, 
+                                        mAudioVideoRec);
+
+                /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                alock.release();
+
+                if (vrc2 == VERR_TIMEOUT)
+                    vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                AssertRC(vrc2);
+                VMR3ReqFree(pReq);
+
+                alock.acquire();
+# endif
+            }
         }
 
@@ -9846,10 +9883,65 @@
                          static_cast<Console *>(pConsole),
                          &pVM, NULL);
-
         alock.acquire();
 
-        /* Enable client connections to the server. */
+#ifdef VBOX_WITH_AUDIO_VRDE
+        /* Attach the VRDE audio driver. */
+        IVRDEServer *pVRDEServer = pConsole->i_getVRDEServer();
+        if (pVRDEServer)
+        {
+            BOOL fVRDEEnabled = FALSE;
+            rc = pVRDEServer->COMGETTER(Enabled)(&fVRDEEnabled);
+            AssertComRCReturnVoid(rc);
+
+            if (fVRDEEnabled)
+            {
+                PVMREQ pReq;
+                int vrc2 = VMR3ReqCallU(pConsole->mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                        (PFNRT)AudioVRDE::Attach, 1, 
+                                        pConsole->mAudioVRDE);
+
+                /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                alock.release();
+
+                if (vrc2 == VERR_TIMEOUT)
+                    vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                AssertRC(vrc2);
+                VMR3ReqFree(pReq);
+
+                alock.acquire();
+            }
+        }
+#endif
+
+        /* Enable client connections to the VRDP server. */
         pConsole->i_consoleVRDPServer()->EnableConnections();
 
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+        Display *pDisplay = pConsole->i_getDisplay();
+        AssertPtr(pDisplay);
+        if (pDisplay)
+        {
+            pDisplay->i_videoRecInvalidate();
+
+            /* Attach the video recording audio driver if required. */
+            if (pDisplay->i_videoRecGetEnabled() & VIDEORECFEATURE_AUDIO)
+            {
+                PVMREQ pReq;
+                int vrc2 = VMR3ReqCallU(pConsole->mpUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
+                                        (PFNRT)AudioVideoRec::Attach, 1, 
+                                        pConsole->mAudioVideoRec);
+
+                /* Release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
+                alock.release();
+
+                if (vrc2 == VERR_TIMEOUT)
+                    vrc2 = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
+                AssertRC(vrc2);
+                VMR3ReqFree(pReq);
+
+                alock.acquire();
+            }
+        }
+#endif
         if (RT_SUCCESS(vrc))
         {
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 70562)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 70563)
@@ -124,4 +124,7 @@
 #ifdef VBOX_WITH_AUDIO_VRDE
 # include "DrvAudioVRDE.h"
+#endif
+#ifdef VBOX_WITH_AUDIO_VIDEOREC
+# include "DrvAudioVideoRec.h"
 #endif
 #include "NetworkServiceRunner.h"
@@ -2967,32 +2970,13 @@
 
 #ifdef VBOX_WITH_AUDIO_VRDE
-            BOOL fVRDEEnabled = FALSE;
-
-            if (mVRDEServer)
-            {
-                hrc = mVRDEServer->COMGETTER(Enabled)(&fVRDEEnabled);
-                ComAssertComRC(hrc);
-            }
-
-            AudioDriverCfg Cfg(strAudioDevice, 0 /* Instance */, uAudioLUN, "AudioVRDE");
-            rc = mAudioVRDE->Configure(&Cfg, RT_BOOL(fVRDEEnabled) /* Attach */);
-            if (   RT_SUCCESS(rc)
-                && fVRDEEnabled) /* Successfully configured, use next LUN for drivers below. */
-            {
-                uAudioLUN++;
-            }
+            AudioDriverCfg DrvCfgVRDE(strAudioDevice, 0 /* Instance */, "AudioVRDE");
+            rc = mAudioVRDE->Initialize(&DrvCfgVRDE);
+            AssertRC(rc);
 #endif /* VBOX_WITH_AUDIO_VRDE */
 
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-            Display *pDisplay = i_getDisplay();
-            if (pDisplay)
-            {
-                /* Note: Don't do any driver attaching (fAttachDetach) here, as this will
-                 *       be done automatically as part of the VM startup process. */
-                rc = pDisplay->i_videoRecConfigure(pDisplay, pDisplay->i_videoRecGetConfig(), false /* fAttachDetach */,
-                                                   &uAudioLUN);
-                if (RT_SUCCESS(rc)) /* Successfully configured, use next LUN for drivers below. */
-                    uAudioLUN++;
-            }
+            AudioDriverCfg DrvCfgVideoRec(strAudioDevice, 0 /* Instance */, "AudioVideoRec");
+            rc = mAudioVideoRec->Initialize(&DrvCfgVideoRec);
+            AssertRC(rc);
 #endif /* VBOX_WITH_AUDIO_VIDEOREC */
 
Index: /trunk/src/VBox/Main/src-client/DisplayImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 70562)
+++ /trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 70563)
@@ -2417,103 +2417,14 @@
 }
 
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
 /**
- * Configures the video recording audio driver in CFGM.
- *
- * @returns VBox status code.
- * @param   strDevice           The PDM device name.
- * @param   uInstance           The PDM device instance.
- * @param   uLUN                The PDM LUN number of the driver.
- * @param   fAttach             Whether to attach or detach the driver configuration to CFGM.
- *
- * @thread EMT
+ * Invalidates the video recording configuration.
  */
-int Display::i_videoRecConfigureAudioDriver(const Utf8Str& strDevice,
-                                            unsigned       uInstance,
-                                            unsigned       uLUN,
-                                            bool           fAttach)
-{
-    if (strDevice.isEmpty()) /* No audio device configured. Bail out. */
-        return VINF_SUCCESS;
-
+void Display::i_videoRecInvalidate(void)
+{
     AssertPtr(mParent);
-
     ComPtr<IMachine> pMachine = mParent->i_machine();
     Assert(pMachine.isNotNull());
 
-    Console::SafeVMPtr ptrVM(mParent);
-    Assert(ptrVM.isOk());
-
-    PUVM pUVM = ptrVM.rawUVM();
-    AssertPtr(pUVM);
-
-    PCFGMNODE pRoot   = CFGMR3GetRootU(pUVM);
-    AssertPtr(pRoot);
-    PCFGMNODE pDev0   = CFGMR3GetChildF(pRoot, "Devices/%s/%u/", strDevice.c_str(), uInstance);
-    AssertPtr(pDev0);
-
-    PCFGMNODE pDevLun = CFGMR3GetChildF(pDev0, "LUN#%u/", uLUN);
-
-    if (fAttach)
-    {
-        if (!pDevLun)
-        {
-            LogRel2(("VideoRec: Attaching audio driver\n"));
-
-            PCFGMNODE pLunL0;
-            CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%RU8", uLUN);
-            CFGMR3InsertString(pLunL0, "Driver", "AUDIO");
-
-            PCFGMNODE pCfg;
-            CFGMR3InsertNode(pLunL0,   "Config", &pCfg);
-                CFGMR3InsertString (pCfg, "DriverName",    "AudioVideoRec");
-                CFGMR3InsertInteger(pCfg, "InputEnabled",  0);
-                CFGMR3InsertInteger(pCfg, "OutputEnabled", 1);
-
-            PCFGMNODE pLunL1;
-            CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1);
-                CFGMR3InsertString(pLunL1, "Driver", "AudioVideoRec");
-
-                CFGMR3InsertNode(pLunL1, "Config", &pCfg);
-                    CFGMR3InsertInteger(pCfg, "Object",        (uintptr_t)mParent->i_getAudioVideoRec());
-                    CFGMR3InsertInteger(pCfg, "ObjectConsole", (uintptr_t)mParent /* Console */);
-        }
-    }
-    else /* Detach */
-    {
-        if (pDevLun)
-        {
-            LogRel2(("VideoRec: Detaching audio driver\n"));
-            CFGMR3RemoveNode(pDevLun);
-        }
-    }
-
-    return VINF_SUCCESS;
-}
-#endif
-
-/**
- * Configures video capturing (via CFGM) and attaches / detaches the associated driver.
- * Currently this only is the audio driver (if available).
- *
- * @returns IPRT status code.
- * @param   pThis               Display instance to configure video capturing for.
- * @param   pCfg                Where to store the configuration into.
- * @param   fAttachDetach       Whether to attach/detach associated drivers or not.
- * @param   puLUN               On input, this defines the LUN to which the audio driver shall be assigned to.
- *                              On output, this returns the LUN the audio driver was assigned to.
- */
-/* static */
-DECLCALLBACK(int) Display::i_videoRecConfigure(Display *pThis, PVIDEORECCFG pCfg, bool fAttachDetach, unsigned *puLUN)
-{
-    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
-    AssertPtrReturn(puLUN, VERR_INVALID_POINTER);
-
-    AssertPtr(pThis->mParent);
-    ComPtr<IMachine> pMachine = pThis->mParent->i_machine();
-    Assert(pMachine.isNotNull());
-
-    pCfg->enmDst = VIDEORECDEST_FILE; /** @todo Make this configurable once we have more variations. */
+    mVideoRecCfg.enmDst = VIDEORECDEST_FILE; /** @todo Make this configurable once we have more variations. */
 
     /*
@@ -2521,44 +2432,44 @@
      */
     BOOL fEnabled;
-    HRESULT rc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    pCfg->fEnabled = RT_BOOL(fEnabled);
+    HRESULT hrc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);
+    AssertComRCReturnVoid(hrc);
+    mVideoRecCfg.fEnabled = RT_BOOL(fEnabled);
 
     com::SafeArray<BOOL> aScreens;
-    rc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(aScreens));
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-
-    pCfg->aScreens.resize(aScreens.size());
+    hrc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(aScreens));
+    AssertComRCReturnVoid(hrc);
+
+    mVideoRecCfg.aScreens.resize(aScreens.size());
     for (size_t i = 0; i < aScreens.size(); ++i)
-        pCfg->aScreens[i] = aScreens[i];
-
-    rc = pMachine->COMGETTER(VideoCaptureWidth)((ULONG *)&pCfg->Video.uWidth);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureHeight)((ULONG *)&pCfg->Video.uHeight);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureRate)((ULONG *)&pCfg->Video.uRate);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureFPS)((ULONG *)&pCfg->Video.uFPS);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureFile)(pCfg->File.strName.asOutParam());
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureMaxFileSize)((ULONG *)&pCfg->File.uMaxSizeMB);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
-    rc = pMachine->COMGETTER(VideoCaptureMaxTime)((ULONG *)&pCfg->uMaxTimeS);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
+        mVideoRecCfg.aScreens[i] = aScreens[i];
+
+    hrc = pMachine->COMGETTER(VideoCaptureWidth)((ULONG *)&mVideoRecCfg.Video.uWidth);
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureHeight)((ULONG *)&mVideoRecCfg.Video.uHeight);
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureRate)((ULONG *)&mVideoRecCfg.Video.uRate);
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureFPS)((ULONG *)&mVideoRecCfg.Video.uFPS);
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureFile)(mVideoRecCfg.File.strName.asOutParam());
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureMaxFileSize)((ULONG *)&mVideoRecCfg.File.uMaxSizeMB);
+    AssertComRCReturnVoid(hrc);
+    hrc = pMachine->COMGETTER(VideoCaptureMaxTime)((ULONG *)&mVideoRecCfg.uMaxTimeS);
+    AssertComRCReturnVoid(hrc);
     BSTR bstrOptions;
-    rc = pMachine->COMGETTER(VideoCaptureOptions)(&bstrOptions);
-    AssertComRCReturn(rc, VERR_COM_UNEXPECTED);
+    hrc = pMachine->COMGETTER(VideoCaptureOptions)(&bstrOptions);
+    AssertComRCReturnVoid(hrc);
 
     /*
      * Set sensible defaults.
      */
-    pCfg->Video.fEnabled = pCfg->fEnabled;
-
-    if (!pCfg->Video.uFPS) /* Prevent division by zero. */
-        pCfg->Video.uFPS = 15;
+    mVideoRecCfg.Video.fEnabled = mVideoRecCfg.fEnabled;
+
+    if (!mVideoRecCfg.Video.uFPS) /* Prevent division by zero. */
+        mVideoRecCfg.Video.uFPS = 15;
 
 #ifdef VBOX_WITH_LIBVPX
-    pCfg->Video.Codec.VPX.uEncoderDeadline = 1000000 / pCfg->Video.uFPS;
+    mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS;
 #endif
 
@@ -2566,9 +2477,9 @@
      * There be dragons! */
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
-    pCfg->Audio.fEnabled  = false;
+    mVideoRecCfg.Audio.fEnabled  = false;
     /* By default we use 48kHz, 16-bit, stereo for the audio track. */
-    pCfg->Audio.uHz       = 48000;
-    pCfg->Audio.cBits     = 16;
-    pCfg->Audio.cChannels = 2;
+    mVideoRecCfg.Audio.uHz       = 48000;
+    mVideoRecCfg.Audio.cBits     = 16;
+    mVideoRecCfg.Audio.cChannels = 2;
 #endif
 
@@ -2585,13 +2496,13 @@
 #ifdef VBOX_WITH_LIBVPX
             if (value.compare("realtime", Utf8Str::CaseInsensitive) == 0)
-                pCfg->Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME;
+                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME;
             else if (value.compare("good", Utf8Str::CaseInsensitive) == 0)
-                pCfg->Video.Codec.VPX.uEncoderDeadline = 1000000 / pCfg->Video.uFPS;
+                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS;
             else if (value.compare("best", Utf8Str::CaseInsensitive) == 0)
-                pCfg->Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY;
+                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY;
             else
             {
                 LogRel(("VideoRec: Setting quality deadline to '%s'\n", value.c_str()));
-                pCfg->Video.Codec.VPX.uEncoderDeadline = value.toUInt32();
+                mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = value.toUInt32();
 #endif
             }
@@ -2601,5 +2512,5 @@
             if (value.compare("false", Utf8Str::CaseInsensitive) == 0)
             {
-                pCfg->Video.fEnabled = false;
+                mVideoRecCfg.Video.fEnabled = false;
 #ifdef VBOX_WITH_AUDIO_VIDEOREC
                 LogRel(("VideoRec: Only audio will be recorded\n"));
@@ -2612,5 +2523,5 @@
             if (value.compare("true", Utf8Str::CaseInsensitive) == 0)
             {
-                pCfg->Audio.fEnabled = true;
+                mVideoRecCfg.Audio.fEnabled = true;
 
             }
@@ -2624,13 +2535,13 @@
             if (value.compare("low", Utf8Str::CaseInsensitive) == 0)
             {
-                pCfg->Audio.uHz       = 8000;
-                pCfg->Audio.cBits     = 16;
-                pCfg->Audio.cChannels = 1;
+                mVideoRecCfg.Audio.uHz       = 8000;
+                mVideoRecCfg.Audio.cBits     = 16;
+                mVideoRecCfg.Audio.cChannels = 1;
             }
             else if (value.startsWith("med" /* "med[ium]" */, Utf8Str::CaseInsensitive) == 0)
             {
-                pCfg->Audio.uHz       = 22050;
-                pCfg->Audio.cBits     = 16;
-                pCfg->Audio.cChannels = 2;
+                mVideoRecCfg.Audio.uHz       = 22050;
+                mVideoRecCfg.Audio.cBits     = 16;
+                mVideoRecCfg.Audio.cChannels = 2;
             }
             else if (value.compare("high", Utf8Str::CaseInsensitive) == 0)
@@ -2645,79 +2556,17 @@
     } /* while */
 
-    unsigned uLUN = *puLUN;
-
-#ifdef VBOX_WITH_AUDIO_VIDEOREC
-    ComPtr<IAudioAdapter> audioAdapter;
-    rc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());
-    AssertComRC(rc);
-
-    unsigned uInstance = 0;
-
-    Utf8Str strAudioDev = pThis->mParent->i_getAudioAdapterDeviceName(audioAdapter);
-    if (!strAudioDev.isEmpty())
-    {
-        Console::SafeVMPtr ptrVM(pThis->mParent);
-        Assert(ptrVM.isOk());
-
-        /*
-         * Configure + attach audio driver.
-         */
-        int vrc2 = VINF_SUCCESS;
-
-        LogFunc(("Audio fAttachDetach=%RTbool, fEnabled=%RTbool\n", fAttachDetach, pCfg->Audio.fEnabled));
-
-        if (pCfg->Audio.fEnabled) /* Enable */
-        {
-            vrc2 = pThis->i_videoRecConfigureAudioDriver(strAudioDev, uInstance, uLUN, true /* fAttach */);
-            if (   RT_SUCCESS(vrc2)
-                && fAttachDetach)
-            {
-                vrc2 = PDMR3DriverAttach(ptrVM.rawUVM(), strAudioDev.c_str(), uInstance, uLUN, 0 /* fFlags */, NULL /* ppBase */);
-            }
-
-            if (RT_FAILURE(vrc2))
-                LogRel(("VideoRec: Failed to attach audio driver, rc=%Rrc\n", vrc2));
-        }
-        else /* Disable */
-        {
-            if (fAttachDetach)
-                vrc2 = PDMR3DriverDetach(ptrVM.rawUVM(), strAudioDev.c_str(), uInstance, uLUN, "AUDIO",
-                                         0 /* iOccurrence */, 0 /* fFlags */);
-
-            if (RT_SUCCESS(vrc2))
-            {
-                vrc2 = pThis->i_videoRecConfigureAudioDriver(strAudioDev, uInstance, uLUN, false /* fAttach */);
-            }
-
-            if (RT_FAILURE(vrc2))
-                LogRel(("VideoRec: Failed to detach audio driver, rc=%Rrc\n", vrc2));
-        }
-
-        AssertRC(vrc2);
-    }
-    else
-        LogRel2(("VideoRec: No audio hardware configured, skipping to record audio\n"));
-#else
-    RT_NOREF(fAttachDetach);
-#endif
-
     /*
      * Invalidate screens.
      */
-    for (unsigned i = 0; i < pCfg->aScreens.size(); i++)
-    {
-        bool fChanged = pThis->maVideoRecEnabled[i] != RT_BOOL(pCfg->aScreens[i]);
-
-        pThis->maVideoRecEnabled[i] = RT_BOOL(pCfg->aScreens[i]);
-
-        if (fChanged && i < pThis->mcMonitors)
-            pThis->i_videoRecScreenChanged(i);
-
-    }
-
-    if (puLUN)
-        *puLUN = uLUN;
-
-    return S_OK;
+    for (unsigned i = 0; i < mVideoRecCfg.aScreens.size(); i++)
+    {
+        bool fChanged = maVideoRecEnabled[i] != RT_BOOL(mVideoRecCfg.aScreens[i]);
+
+        maVideoRecEnabled[i] = RT_BOOL(mVideoRecCfg.aScreens[i]);
+
+        if (fChanged && i < mcMonitors)
+            i_videoRecScreenChanged(i);
+
+    }
 }
 
Index: /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp	(revision 70562)
+++ /trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp	(revision 70563)
@@ -1016,6 +1016,6 @@
 
 AudioVideoRec::AudioVideoRec(Console *pConsole)
-    : mpDrv(NULL)
-    , mpConsole(pConsole)
+    : AudioDriver(pConsole)
+    , mpDrv(NULL)
 {
 }
@@ -1029,4 +1029,11 @@
         mpDrv = NULL;
     }
+}
+
+
+void AudioVideoRec::configureDriver(PCFGMNODE pLunCfg)
+{
+    CFGMR3InsertInteger(pLunCfg, "Object",        (uintptr_t)mpConsole->i_getAudioVideoRec());
+    CFGMR3InsertInteger(pLunCfg, "ObjectConsole", (uintptr_t)mpConsole);
 }
 
