DrvAudioVRDE.cpp revision a708b5b81c81f03f13980efee2262d4290ba03be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * VRDE audio backend for Main.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Copyright (C) 2013-2015 Oracle Corporation
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This file is part of VirtualBox Open Source Edition (OSE), as
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * available from http://www.virtualbox.org. This file is free software;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * you can redistribute it and/or modify it under the terms of the GNU
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * General Public License (GPL) as published by the Free Software
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Foundation, in version 2 as it comes in the "COPYING" file of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Header Files *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw*******************************************************************************/
8c10a8659ac31335ed870a1711c0182623f72fd6as#include "../../Devices/Audio/DrvAudio.h"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include "../../Devices/Audio/AudioMixBuffer.h"
8c10a8659ac31335ed870a1711c0182623f72fd6as/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Structures and Typedefs *
8c10a8659ac31335ed870a1711c0182623f72fd6as*******************************************************************************/
8c10a8659ac31335ed870a1711c0182623f72fd6as * Audio VRDE driver instance data.
8c10a8659ac31335ed870a1711c0182623f72fd6astypedef struct DRVAUDIOVRDE
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Pointer to audio VRDE object. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the driver instance structure. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the VRDP's console object. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the DrvAudio port interface that is above us. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Whether this driver is enabled or not. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct VRDESTREAMIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Associated host input stream. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Number of samples captured asynchronously in the
8c10a8659ac31335ed870a1711c0182623f72fd6as * onVRDEInputXXX callbacks. */
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Critical section. */
8c10a8659ac31335ed870a1711c0182623f72fd6astypedef struct VRDESTREAMOUT
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Associated host output stream. */
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEInitIn(PPDMIHOSTAUDIO pInterface,
8c10a8659ac31335ed870a1711c0182623f72fd6as PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmIn->HstStrmIn.Props);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb LogFlowFunc(("pHstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg));
8c10a8659ac31335ed870a1711c0182623f72fd6as PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
8c10a8659ac31335ed870a1711c0182623f72fd6as return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmOut->HstStrmOut.Props);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(bool) drvAudioVRDEIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return false;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return true;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * <Missing brief description>
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Transfers audio input formerly sent by a connected RDP client / VRDE backend
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * (using the onVRDEInputXXX methods) over to the VRDE host (VM). The audio device
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * emulation then will read and send the data to the guest.
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @return IPRT status code.
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pInterface
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pHstStrmIn
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pcSamplesCaptured
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(int) drvAudioVRDECaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
8622ec4569457733001d4982ef7f5b44427069beGordon Ross AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pcSamplesCaptured, VERR_INVALID_POINTER);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @todo Use CritSect! */
8622ec4569457733001d4982ef7f5b44427069beGordon Ross rc = audioMixBufMixToParent(&pVRDEStrmIn->HstStrmIn.MixBuf, pVRDEStrmIn->cSamplesCaptured,
8622ec4569457733001d4982ef7f5b44427069beGordon Ross Assert(pVRDEStrmIn->cSamplesCaptured >= cProcessed);
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFunc(("cSamplesCaptured=%RU32, cProcessed=%RU32\n",
8622ec4569457733001d4982ef7f5b44427069beGordon Ross pVRDEStrmIn->cSamplesCaptured, cProcessed, rc));
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * Transfers VM audio output to remote client.
8c10a8659ac31335ed870a1711c0182623f72fd6as * Transfers VM audio output over to the VRDE instance for playing remotely
8c10a8659ac31335ed870a1711c0182623f72fd6as * on the client.
8c10a8659ac31335ed870a1711c0182623f72fd6as * @return IPRT status code.
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pInterface
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pHstStrmOut
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pcSamplesPlayed
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pcSamplesPlayed is optional. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Just call the VRDP server with the data.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t live = drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cSamplesPlayed = (int)((2 * ticks * pHstStrmOut->Props.uHz + ticks_per_second) / ticks_per_second / 2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHstStrmOut->Props.uHz,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* if (!cSamplesToSend)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pcSamplesPlayed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pcSamplesPlayed = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("uFreq=%RU32, cChan=%RU8, cBits=%RU8, fSigned=%RTbool, enmFormat=%ld, cSamplesToSend=%RU32\n",
8c10a8659ac31335ed870a1711c0182623f72fd6as int rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw audioMixBufFinish(&pHstStrmOut->MixBuf, cSamplesToSend);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Always report back all samples acquired, regardless of whether the
8c10a8659ac31335ed870a1711c0182623f72fd6as * VRDP server actually did process those.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("cReadTotal=%RU32, rc=%Rrc\n", cReadTotal, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMAUDIOHSTSTRMIN pThisStrmIn = &pVRDEStrmIn->HstStrmIn;
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Initialize only if not already done. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pThisStrmIn->MixBuf),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThisStrmIn->Props.cChannels, pThisStrmIn->Props.cBits);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("No RDP client connected, so no input recording supported\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pCfg->cMaxHstStrmsIn = 2; /* Microphone in + Line in. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(void) drvAudioVRDEShutdown(PPDMIHOSTAUDIO pInterface)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @interface_method_impl{PDMIBASE,pfnQueryInterface}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(void *) drvAudioVRDEQueryInterface(PPDMIBASE pInterface, const char *pszIID)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint AudioVRDE::onVRDEControl(bool fEnable, uint32_t uFlags)
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowThisFunc(("fEnable=%RTbool, uFlags=0x%x\n", fEnable, uFlags));
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Marks the beginning of sending captured audio data from a connected
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * RDP client.
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh * @return IPRT status code.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * @param pvContext The context; in this case a pointer to a
8c10a8659ac31335ed870a1711c0182623f72fd6as * VRDESTREAMIN structure.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * @param pVRDEAudioBegin Pointer to a VRDEAUDIOINBEGIN structure.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
8c10a8659ac31335ed870a1711c0182623f72fd6as VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), iSampleHz, cChannels, cBits, fUnsigned));
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borregoint AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /** @todo Use CritSect! */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pvData, cbData, &cWritten);
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n",
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Construct a VRDE audio driver instance.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * @copydoc FNPDMDRVCONSTRUCT
8c10a8659ac31335ed870a1711c0182623f72fd6as/* static */
8c10a8659ac31335ed870a1711c0182623f72fd6asDECLCALLBACK(int) AudioVRDE::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh ("Configuration error: Not possible to attach anything to this driver!\n"),
8c10a8659ac31335ed870a1711c0182623f72fd6as * Init the static parts.
8c10a8659ac31335ed870a1711c0182623f72fd6as /* IBase */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* IHostAudio */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* Init defaults. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Get the ConsoleVRDPServer object pointer.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pvUser);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertMsgRCReturn(rc, ("Confguration error: No/bad \"ObjectVRDPServer\" value, rc=%Rrc\n", rc), rc);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser;
8c10a8659ac31335ed870a1711c0182623f72fd6as * Get the AudioVRDE object pointer.
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertMsgRCReturn(rc, ("Confguration error: No/bad \"Object\" value, rc=%Rrc\n", rc), rc);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls.
8c10a8659ac31335ed870a1711c0182623f72fd6as * Described in CFGM tree.
8c10a8659ac31335ed870a1711c0182623f72fd6as pThis->pDrvAudio = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertMsgReturn(pThis->pDrvAudio, ("Configuration error: No upper interface specified!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE);
8c10a8659ac31335ed870a1711c0182623f72fd6as * @interface_method_impl{PDMDRVREG,pfnDestruct}
8c10a8659ac31335ed870a1711c0182623f72fd6as/* static */
8c10a8659ac31335ed870a1711c0182623f72fd6asDECLCALLBACK(void) AudioVRDE::drvDestruct(PPDMDRVINS pDrvIns)
8c10a8659ac31335ed870a1711c0182623f72fd6as PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
8c10a8659ac31335ed870a1711c0182623f72fd6as * If the AudioVRDE object is still alive, we must clear it's reference to
8c10a8659ac31335ed870a1711c0182623f72fd6as * us since we'll be invalid when we return from this method.
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh * VRDE audio driver registration record.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szName */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szRCMod */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szR0Mod */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pszDescription */
54207fd2e1e7ed01d0416da8cf296dbef920fbfcJerry Jelinek "Audio driver for VRDE backend",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* fFlags */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* fClass. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* cMaxInstances */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* cbInstance */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pfnConstruct */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pfnDestruct */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnRelocate */
8c10a8659ac31335ed870a1711c0182623f72fd6as /* pfnIOCtl */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnPowerOn */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnReset */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnSuspend */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnResume */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnAttach */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnDetach */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnPowerOff */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnSoftReset */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* u32EndVersion */