DrvAudioVRDE.cpp revision 174f3dff60f96d89b320f9a322307118676db1db
/* $Id$ */
/** @file
* VRDE audio backend for Main.
*/
/*
* Copyright (C) 2013-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "DrvAudioVRDE.h"
#include "ConsoleImpl.h"
#include "ConsoleVRDPServer.h"
#include "Logging.h"
#include "../../Devices/Audio/DrvAudio.h"
#include "../../Devices/Audio/AudioMixBuffer.h"
#ifdef LOG_GROUP
#endif
#define LOG_GROUP LOG_GROUP_DEV_AUDIO
/**
* Audio VRDE driver instance data.
*/
typedef struct DRVAUDIOVRDE
{
/** Pointer to audio VRDE object. */
/** Pointer to the driver instance structure. */
/** Pointer to the DrvAudio port interface that is above it. */
typedef struct VRDESTREAMIN
{
/** Associated host input stream. */
/** Number of samples captured asynchronously in the
* onVRDEInputXXX callbacks. */
/** Critical section. */
typedef struct VRDESTREAMOUT
{
/** Associated host output stream. */
{
return VINF_SUCCESS;
}
{
if (pcSamples)
}
{
if (pcSamples)
}
/**
* Transfers audio input formerly sent by a connected RDP client / VRDE backend
* (using the onVRDEInputXXX methods) over to the VRDE host (VM). The audio device
* emulation then will read and send the data to the guest.
*
* @return IPRT status code.
* @param pInterface
* @param pHstStrmIn
* @param pcSamplesCaptured
*/
static DECLCALLBACK(int) drvAudioVRDECaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
{
/** @todo Use CritSect! */
int rc;
uint32_t cProcessed = 0;
if (pVRDEStrmIn->cSamplesCaptured)
{
&cProcessed);
}
else
rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
}
LogFlowFunc(("cSamplesCaptured=%RU32, cProcessed=%RU32\n",
return rc;
}
/**
* Transfers VM audio output over to the VRDE instance for playing remotely
* on the client.
*
* @return IPRT status code.
* @param pInterface
* @param pHstStrmOut
* @param pcSamplesPlayed
*/
static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
{
/* pcSamplesPlayed is optional. */
/*
* Just call the VRDP server with the data.
*/
uint32_t cSamplesPlayed = (int)((2 * ticks * pHstStrmOut->Props.uHz + ticks_per_second) / ticks_per_second / 2);
if (!cSamplesPlayed)
LogFlowFunc(("hz=%d, chan=%d, cBits=%d, fSigned=%RTbool, format=%ld\n",
format));
uint32_t cReadTotal = 0;
if (RT_SUCCESS(rc))
{
cReadTotal = cRead;
if (rc == VINF_TRY_AGAIN)
{
if (RT_SUCCESS(rc))
{
cReadTotal += cRead;
}
}
}
if (pcSamplesPlayed)
return rc;
}
static DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
{
if (pDrv->pConsoleVRDPServer)
return VINF_SUCCESS;
}
static DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
{
return VINF_SUCCESS;
}
static DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
{
return VINF_SUCCESS;
}
static DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn2, /** @todo Fix param types! */
{
/* Initialize only if not already done. */
if (enmStreamCmd == PDMAUDIOSTREAMCMD_ENABLE)
{
int rc2 = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pHstStrmIn->MixBuf),
#ifdef DEBUG
if (rc2 == VERR_NOT_SUPPORTED)
LogFlowFunc(("No RDP client connected, so no input recording supported\n"));
#endif
}
else if (enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE)
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
{
return NULL;
}
{
}
{
if (mpDrv)
{
}
}
{
return VINF_SUCCESS; /* Never veto. */
}
/**
* Marks the beginning of sending captured audio data from a connected
* RDP client.
*
* @return IPRT status code.
* @param pvContext The context; in this case a pointer to a
* VRDESTREAMIN structure.
* @param pVRDEAudioBegin Pointer to a VRDEAUDIOINBEGIN structure.
*/
{
/*pVRDEStrmIn->cbSample = VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt);
pVRDEStrmIn->uHz = iSampleHz;*/
LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
return VINF_SUCCESS;
}
{
/** @todo Use CritSect! */
if (RT_SUCCESS(rc))
LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n",
return rc;
}
{
return VINF_SUCCESS;
}
/**
* Construct a VRDE audio driver instance.
*
* @copydoc FNPDMDRVCONSTRUCT
*/
/* static */
{
LogRel(("Audio: Initializing VRDE driver\n"));
("Configuration error: Not possible to attach anything to this driver!\n"),
/*
* Init the static parts.
*/
/* IBase */
/* Get VRDPServer pointer. */
void *pvUser;
if (RT_FAILURE(rc))
{
return rc;
}
/* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Get the interface for the above driver (DrvAudio) to make mixer/conversion calls.
* Described in CFGM tree.
*/
{
AssertMsgFailed(("Configuration error: No upper interface specified!\n"));
return VERR_PDM_MISSING_INTERFACE_ABOVE;
}
return VINF_SUCCESS;
}
/* static */
{
}
/**
* VRDE audio driver registration record.
*/
{
/* szName */
"AudioVRDE",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"Audio driver for VRDE backend",
/* fFlags */
/* fClass. */
/* cMaxInstances */
~0U,
/* cbInstance */
sizeof(DRVAUDIOVRDE),
/* pfnConstruct */
/* pfnDestruct */
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
};