DrvAudioVRDE.cpp revision a708b5b81c81f03f13980efee2262d4290ba03be
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* $Id$ */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/** @file
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * VRDE audio backend for Main.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Copyright (C) 2013-2015 Oracle Corporation
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
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
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Header Files *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw*******************************************************************************/
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh#include "DrvAudioVRDE.h"
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include "ConsoleImpl.h"
54207fd2e1e7ed01d0416da8cf296dbef920fbfcJerry Jelinek#include "ConsoleVRDPServer.h"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include "Logging.h"
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown
8c10a8659ac31335ed870a1711c0182623f72fd6as#include "../../Devices/Audio/DrvAudio.h"
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include "../../Devices/Audio/AudioMixBuffer.h"
8c10a8659ac31335ed870a1711c0182623f72fd6as
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <iprt/mem.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <iprt/cdefs.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <iprt/circbuf.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <VBox/vmm/pdmaudioifs.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as#include <VBox/vmm/pdmdrv.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as#include <VBox/RemoteDesktop/VRDE.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as#include <VBox/vmm/cfgm.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as#include <VBox/err.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as#undef LOG_GROUP
8c10a8659ac31335ed870a1711c0182623f72fd6as#define LOG_GROUP LOG_GROUP_DEV_AUDIO
8c10a8659ac31335ed870a1711c0182623f72fd6as#include <VBox/log.h>
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as/*******************************************************************************
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw* Structures and Typedefs *
8c10a8659ac31335ed870a1711c0182623f72fd6as*******************************************************************************/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
8c10a8659ac31335ed870a1711c0182623f72fd6as * Audio VRDE driver instance data.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
8c10a8659ac31335ed870a1711c0182623f72fd6astypedef struct DRVAUDIOVRDE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Pointer to audio VRDE object. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AudioVRDE *pAudioVRDE;
8c10a8659ac31335ed870a1711c0182623f72fd6as PPDMDRVINS pDrvIns;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the driver instance structure. */
8c10a8659ac31335ed870a1711c0182623f72fd6as PDMIHOSTAUDIO IHostAudio;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the VRDP's console object. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ConsoleVRDPServer *pConsoleVRDPServer;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Pointer to the DrvAudio port interface that is above us. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMIAUDIOCONNECTOR pDrvAudio;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Whether this driver is enabled or not. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bool fEnabled;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwtypedef struct VRDESTREAMIN
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Associated host input stream. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMAUDIOHSTSTRMIN HstStrmIn;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** Number of samples captured asynchronously in the
8c10a8659ac31335ed870a1711c0182623f72fd6as * onVRDEInputXXX callbacks. */
8c10a8659ac31335ed870a1711c0182623f72fd6as uint32_t cSamplesCaptured;
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Critical section. */
8c10a8659ac31335ed870a1711c0182623f72fd6as RTCRITSECT CritSect;
8c10a8659ac31335ed870a1711c0182623f72fd6as} VRDESTREAMIN, *PVRDESTREAMIN;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6astypedef struct VRDESTREAMOUT
8c10a8659ac31335ed870a1711c0182623f72fd6as{
8c10a8659ac31335ed870a1711c0182623f72fd6as /** Associated host output stream. */
8c10a8659ac31335ed870a1711c0182623f72fd6as PDMAUDIOHSTSTRMOUT HstStrmOut;
8c10a8659ac31335ed870a1711c0182623f72fd6as uint64_t old_ticks;
8c10a8659ac31335ed870a1711c0182623f72fd6as uint64_t cSamplesSentPerSec;
8c10a8659ac31335ed870a1711c0182623f72fd6as} VRDESTREAMOUT, *PVRDESTREAMOUT;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFuncEnter();
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as return VINF_SUCCESS;
8c10a8659ac31335ed870a1711c0182623f72fd6as}
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEInitIn(PPDMIHOSTAUDIO pInterface,
8c10a8659ac31335ed870a1711c0182623f72fd6as PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
8c10a8659ac31335ed870a1711c0182623f72fd6as PDMAUDIORECSOURCE enmRecSource,
8c10a8659ac31335ed870a1711c0182623f72fd6as uint32_t *pcSamples)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
8c10a8659ac31335ed870a1711c0182623f72fd6as PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (pcSamples)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb *pcSamples = _4K; /** @todo Make this configurable. */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmIn->HstStrmIn.Props);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb uint32_t *pcSamples)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb{
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb LogFlowFunc(("pHstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg));
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
8c10a8659ac31335ed870a1711c0182623f72fd6as PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
8c10a8659ac31335ed870a1711c0182623f72fd6as AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as if (pcSamples)
8c10a8659ac31335ed870a1711c0182623f72fd6as *pcSamples = _4K; /** @todo Make this configurable. */
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmOut->HstStrmOut.Props);
8c10a8659ac31335ed870a1711c0182623f72fd6as}
8c10a8659ac31335ed870a1711c0182623f72fd6as
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(bool) drvAudioVRDEIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb{
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pDrv, false);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb NOREF(enmDir);
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb if (!pDrv->fEnabled)
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return false;
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb return true;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/**
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * <Missing brief description>
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb *
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 *
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @return IPRT status code.
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pInterface
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pHstStrmIn
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * @param pcSamplesCaptured
8622ec4569457733001d4982ef7f5b44427069beGordon Ross */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic DECLCALLBACK(int) drvAudioVRDECaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t *pcSamplesCaptured)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
8622ec4569457733001d4982ef7f5b44427069beGordon Ross AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pcSamplesCaptured, VERR_INVALID_POINTER);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
8622ec4569457733001d4982ef7f5b44427069beGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
8622ec4569457733001d4982ef7f5b44427069beGordon Ross PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
8c10a8659ac31335ed870a1711c0182623f72fd6as AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /** @todo Use CritSect! */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cProcessed = 0;
8622ec4569457733001d4982ef7f5b44427069beGordon Ross if (pVRDEStrmIn->cSamplesCaptured)
8622ec4569457733001d4982ef7f5b44427069beGordon Ross {
8622ec4569457733001d4982ef7f5b44427069beGordon Ross rc = audioMixBufMixToParent(&pVRDEStrmIn->HstStrmIn.MixBuf, pVRDEStrmIn->cSamplesCaptured,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &cProcessed);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
8c10a8659ac31335ed870a1711c0182623f72fd6as else
8c10a8659ac31335ed870a1711c0182623f72fd6as rc = VINF_SUCCESS;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8622ec4569457733001d4982ef7f5b44427069beGordon Ross if (RT_SUCCESS(rc))
8622ec4569457733001d4982ef7f5b44427069beGordon Ross {
8622ec4569457733001d4982ef7f5b44427069beGordon Ross *pcSamplesCaptured = cProcessed;
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
8622ec4569457733001d4982ef7f5b44427069beGordon Ross Assert(pVRDEStrmIn->cSamplesCaptured >= cProcessed);
8622ec4569457733001d4982ef7f5b44427069beGordon Ross pVRDEStrmIn->cSamplesCaptured -= cProcessed;
8622ec4569457733001d4982ef7f5b44427069beGordon Ross }
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFunc(("cSamplesCaptured=%RU32, cProcessed=%RU32\n",
8622ec4569457733001d4982ef7f5b44427069beGordon Ross pVRDEStrmIn->cSamplesCaptured, cProcessed, rc));
8c10a8659ac31335ed870a1711c0182623f72fd6as return rc;
8c10a8659ac31335ed870a1711c0182623f72fd6as}
8622ec4569457733001d4982ef7f5b44427069beGordon Ross
8622ec4569457733001d4982ef7f5b44427069beGordon Ross/**
8622ec4569457733001d4982ef7f5b44427069beGordon Ross * Transfers VM audio output to remote client.
8c10a8659ac31335ed870a1711c0182623f72fd6as *
8c10a8659ac31335ed870a1711c0182623f72fd6as * Transfers VM audio output over to the VRDE instance for playing remotely
8c10a8659ac31335ed870a1711c0182623f72fd6as * on the client.
8c10a8659ac31335ed870a1711c0182623f72fd6as *
8c10a8659ac31335ed870a1711c0182623f72fd6as * @return IPRT status code.
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pInterface
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pHstStrmOut
8c10a8659ac31335ed870a1711c0182623f72fd6as * @param pcSamplesPlayed
8c10a8659ac31335ed870a1711c0182623f72fd6as */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t *pcSamplesPlayed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pcSamplesPlayed is optional. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
8c10a8659ac31335ed870a1711c0182623f72fd6as AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Just call the VRDP server with the data.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t live = drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t ticks = now - pVRDEStrmOut->old_ticks;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cSamplesPlayed = (int)((2 * ticks * pHstStrmOut->Props.uHz + ticks_per_second) / ticks_per_second / 2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!cSamplesPlayed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cSamplesPlayed = live;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHstStrmOut->Props.uHz,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pHstStrmOut->Props.cChannels,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pHstStrmOut->Props.cBits,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pHstStrmOut->Props.fSigned);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pVRDEStrmOut->old_ticks = now;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int cSamplesToSend = live;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* if (!cSamplesToSend)
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pcSamplesPlayed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pcSamplesPlayed = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("uFreq=%RU32, cChan=%RU8, cBits=%RU8, fSigned=%RTbool, enmFormat=%ld, cSamplesToSend=%RU32\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pHstStrmOut->Props.uHz, pHstStrmOut->Props.cChannels,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pHstStrmOut->Props.cBits, pHstStrmOut->Props.fSigned,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw format, cSamplesToSend));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cReadTotal = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMAUDIOSAMPLE pSamples;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw uint32_t cRead;
8c10a8659ac31335ed870a1711c0182623f72fd6as int rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &pSamples, &cRead);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ( RT_SUCCESS(rc)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw && cRead)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cReadTotal = cRead;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == VINF_TRY_AGAIN)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw &pSamples, &cRead);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (RT_SUCCESS(rc))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw cReadTotal += cRead;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw audioMixBufFinish(&pHstStrmOut->MixBuf, cSamplesToSend);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Always report back all samples acquired, regardless of whether the
8c10a8659ac31335ed870a1711c0182623f72fd6as * VRDP server actually did process those.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pcSamplesPlayed)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *pcSamplesPlayed = cReadTotal;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("cReadTotal=%RU32, rc=%Rrc\n", cReadTotal, rc));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pDrv->pConsoleVRDPServer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return VINF_SUCCESS;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDMAUDIOSTREAMCMD enmStreamCmd)
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
8c10a8659ac31335ed870a1711c0182623f72fd6as PVRDESTREAMIN pVRDEStrmOut = (PVRDESTREAMIN)pHstStrmOut;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw audioMixBufReset(&pHstStrmOut->MixBuf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMAUDIOSTREAMCMD enmStreamCmd)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PPDMAUDIOHSTSTRMIN pThisStrmIn = &pVRDEStrmIn->HstStrmIn;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!pDrv->pConsoleVRDPServer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
8c10a8659ac31335ed870a1711c0182623f72fd6as audioMixBufReset(&pThisStrmIn->MixBuf);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Initialize only if not already done. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (enmStreamCmd == PDMAUDIOSTREAMCMD_ENABLE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pThisStrmIn->MixBuf),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThisStrmIn->Props.uHz,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pThisStrmIn->Props.cChannels, pThisStrmIn->Props.cBits);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc == VERR_NOT_SUPPORTED)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LogFlowFunc(("No RDP client connected, so no input recording supported\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else if (enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross rc = VINF_SUCCESS;
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return rc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
8c10a8659ac31335ed870a1711c0182623f72fd6asstatic DECLCALLBACK(int) drvAudioVRDEGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pCfg->cbStreamOut = sizeof(VRDESTREAMOUT);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pCfg->cbStreamIn = sizeof(VRDESTREAMIN);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pCfg->cMaxHstStrmsOut = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pCfg->cMaxHstStrmsIn = 2; /* Microphone in + Line in. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return VINF_SUCCESS;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(void) drvAudioVRDEShutdown(PPDMIHOSTAUDIO pInterface)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw AssertPtrReturnVoid(pDrv);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (pDrv->pConsoleVRDPServer)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross/**
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * @interface_method_impl{PDMIBASE,pfnQueryInterface}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic DECLCALLBACK(void *) drvAudioVRDEQueryInterface(PPDMIBASE pInterface, const char *pszIID)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
8c10a8659ac31335ed870a1711c0182623f72fd6as PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return NULL;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwAudioVRDE::AudioVRDE(Console *pConsole)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw : mpDrv(NULL),
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mParent(pConsole)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwAudioVRDE::~AudioVRDE(void)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (mpDrv)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mpDrv->pAudioVRDE = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mpDrv = NULL;
ccc71be50bb49efb4e31004c77fb3e065e9c0596Gordon Ross }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint AudioVRDE::onVRDEControl(bool fEnable, uint32_t uFlags)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowThisFunc(("fEnable=%RTbool, uFlags=0x%x\n", fEnable, uFlags));
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as if (mpDrv == NULL)
8c10a8659ac31335ed870a1711c0182623f72fd6as return VERR_INVALID_STATE;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as mpDrv->fEnabled = fEnable;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as return VINF_SUCCESS; /* Never veto. */
8c10a8659ac31335ed870a1711c0182623f72fd6as}
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego/**
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Marks the beginning of sending captured audio data from a connected
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * RDP client.
8c10a8659ac31335ed870a1711c0182623f72fd6as *
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 Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as int iSampleHz = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);
8c10a8659ac31335ed870a1711c0182623f72fd6as int cChannels = VRDE_AUDIO_FMT_CHANNELS(audioFmt);
8c10a8659ac31335ed870a1711c0182623f72fd6as int cBits = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt);
8c10a8659ac31335ed870a1711c0182623f72fd6as bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);
8c10a8659ac31335ed870a1711c0182623f72fd6as
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));
8c10a8659ac31335ed870a1711c0182623f72fd6as
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego return VINF_SUCCESS;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego}
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borregoint AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego{
8c10a8659ac31335ed870a1711c0182623f72fd6as PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
8c10a8659ac31335ed870a1711c0182623f72fd6as
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /** @todo Use CritSect! */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego uint32_t cWritten;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pvData, cbData, &cWritten);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego if (RT_SUCCESS(rc))
8c10a8659ac31335ed870a1711c0182623f72fd6as pVRDEStrmIn->cSamplesCaptured += cWritten;
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n",
8c10a8659ac31335ed870a1711c0182623f72fd6as cbData, cWritten, pVRDEStrmIn->cSamplesCaptured, rc));
8c10a8659ac31335ed870a1711c0182623f72fd6as return rc;
8c10a8659ac31335ed870a1711c0182623f72fd6as}
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6asint AudioVRDE::onVRDEInputEnd(void *pvContext)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego NOREF(pvContext);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego return VINF_SUCCESS;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego}
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
8c10a8659ac31335ed870a1711c0182623f72fd6asint AudioVRDE::onVRDEInputIntercept(bool fEnabled)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
8c10a8659ac31335ed870a1711c0182623f72fd6as return VINF_SUCCESS; /* Never veto. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego/**
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Construct a VRDE audio driver instance.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * @copydoc FNPDMDRVCONSTRUCT
8c10a8659ac31335ed870a1711c0182623f72fd6as */
8c10a8659ac31335ed870a1711c0182623f72fd6as/* static */
8c10a8659ac31335ed870a1711c0182623f72fd6asDECLCALLBACK(int) AudioVRDE::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
8c10a8659ac31335ed870a1711c0182623f72fd6as LogRel(("Audio: Initializing VRDE driver\n"));
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh LogFlowFunc(("fFlags=0x%x\n", fFlags));
8c10a8659ac31335ed870a1711c0182623f72fd6as
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh ("Configuration error: Not possible to attach anything to this driver!\n"),
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego VERR_PDM_DRVINS_NO_ATTACH);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /*
8c10a8659ac31335ed870a1711c0182623f72fd6as * Init the static parts.
8c10a8659ac31335ed870a1711c0182623f72fd6as */
8c10a8659ac31335ed870a1711c0182623f72fd6as pThis->pDrvIns = pDrvIns;
8c10a8659ac31335ed870a1711c0182623f72fd6as /* IBase */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* IHostAudio */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego PDMAUDIO_IHOSTAUDIO_CALLBACKS(drvAudioVRDE);
8c10a8659ac31335ed870a1711c0182623f72fd6as
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* Init defaults. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross pThis->fEnabled = false;
8c10a8659ac31335ed870a1711c0182623f72fd6as
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Get the ConsoleVRDPServer object pointer.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross void *pvUser;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pvUser);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AssertMsgRCReturn(rc, ("Confguration error: No/bad \"ObjectVRDPServer\" value, rc=%Rrc\n", rc), rc);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser;
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /*
8c10a8659ac31335ed870a1711c0182623f72fd6as * Get the AudioVRDE object pointer.
8c10a8659ac31335ed870a1711c0182623f72fd6as */
8c10a8659ac31335ed870a1711c0182623f72fd6as pvUser = NULL;
8c10a8659ac31335ed870a1711c0182623f72fd6as rc = CFGMR3QueryPtr(pCfg, "Object", &pvUser);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego AssertMsgRCReturn(rc, ("Confguration error: No/bad \"Object\" value, rc=%Rrc\n", rc), rc);
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego pThis->pAudioVRDE = (AudioVRDE *)pvUser;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego pThis->pAudioVRDE->mpDrv = pThis;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /*
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls.
8c10a8659ac31335ed870a1711c0182623f72fd6as * Described in CFGM tree.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
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);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego return VINF_SUCCESS;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego}
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as/**
8c10a8659ac31335ed870a1711c0182623f72fd6as * @interface_method_impl{PDMDRVREG,pfnDestruct}
8c10a8659ac31335ed870a1711c0182623f72fd6as */
8c10a8659ac31335ed870a1711c0182623f72fd6as/* static */
8c10a8659ac31335ed870a1711c0182623f72fd6asDECLCALLBACK(void) AudioVRDE::drvDestruct(PPDMDRVINS pDrvIns)
8c10a8659ac31335ed870a1711c0182623f72fd6as{
8c10a8659ac31335ed870a1711c0182623f72fd6as PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
8c10a8659ac31335ed870a1711c0182623f72fd6as PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
8c10a8659ac31335ed870a1711c0182623f72fd6as LogFlowFuncEnter();
8c10a8659ac31335ed870a1711c0182623f72fd6as
8c10a8659ac31335ed870a1711c0182623f72fd6as /*
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.
8c10a8659ac31335ed870a1711c0182623f72fd6as */
8c10a8659ac31335ed870a1711c0182623f72fd6as if (pThis->pAudioVRDE)
8c10a8659ac31335ed870a1711c0182623f72fd6as {
8c10a8659ac31335ed870a1711c0182623f72fd6as pThis->pAudioVRDE->mpDrv = NULL;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego pThis->pAudioVRDE = NULL;
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego }
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego}
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego
8c10a8659ac31335ed870a1711c0182623f72fd6as/**
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh * VRDE audio driver registration record.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossconst PDMDRVREG AudioVRDE::DrvReg =
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDM_DRVREG_VERSION,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szName */
54207fd2e1e7ed01d0416da8cf296dbef920fbfcJerry Jelinek "AudioVRDE",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szRCMod */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross "",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* szR0Mod */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross "",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pszDescription */
54207fd2e1e7ed01d0416da8cf296dbef920fbfcJerry Jelinek "Audio driver for VRDE backend",
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* fFlags */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* fClass. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross PDM_DRVREG_CLASS_AUDIO,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* cMaxInstances */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ~0U,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* cbInstance */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sizeof(DRVAUDIOVRDE),
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pfnConstruct */
8c10a8659ac31335ed870a1711c0182623f72fd6as AudioVRDE::drvConstruct,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* pfnDestruct */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross AudioVRDE::drvDestruct,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnRelocate */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross NULL,
8c10a8659ac31335ed870a1711c0182623f72fd6as /* pfnIOCtl */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnPowerOn */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnReset */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnSuspend */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnResume */
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnAttach */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* pfnDetach */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh NULL,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnPowerOff */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh NULL,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh /* pfnSoftReset */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh NULL,
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego /* u32EndVersion */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh PDM_DRVREG_VERSION
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego};
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh
2c2961f8403049d948b9f3e6c35d6488b6b7e1aajose borrego