DrvAudioVRDE.cpp revision 5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7
20593760b116c90f3e439552763eef632a3bbb17vboxsync * VBox Audio VRDE backend
20593760b116c90f3e439552763eef632a3bbb17vboxsync * Copyright (C) 2006-2010 Oracle Corporation
20593760b116c90f3e439552763eef632a3bbb17vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
20593760b116c90f3e439552763eef632a3bbb17vboxsync * available from http://www.virtualbox.org. This file is free software;
20593760b116c90f3e439552763eef632a3bbb17vboxsync * you can redistribute it and/or modify it under the terms of the GNU
20593760b116c90f3e439552763eef632a3bbb17vboxsync * General Public License (GPL) as published by the Free Software
20593760b116c90f3e439552763eef632a3bbb17vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
20593760b116c90f3e439552763eef632a3bbb17vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
20593760b116c90f3e439552763eef632a3bbb17vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20593760b116c90f3e439552763eef632a3bbb17vboxsync/*******************************************************************************
20593760b116c90f3e439552763eef632a3bbb17vboxsync * IO Ring Buffer section
20593760b116c90f3e439552763eef632a3bbb17vboxsync ******************************************************************************/
20593760b116c90f3e439552763eef632a3bbb17vboxsync/* Implementation of a lock free ring buffer which could be used in a multi
20593760b116c90f3e439552763eef632a3bbb17vboxsync * threaded environment. Note that only the acquire, release and getter
20593760b116c90f3e439552763eef632a3bbb17vboxsync * functions are threading aware. So don't use reset if the ring buffer is
20593760b116c90f3e439552763eef632a3bbb17vboxsync * still in use. */
20593760b116c90f3e439552763eef632a3bbb17vboxsynctypedef struct IORINGBUFFER
ea9fe8748652b3e7b3f1245001f9d7cd8c9eaaccvboxsync /* The current read position in the buffer */
20593760b116c90f3e439552763eef632a3bbb17vboxsync /* The current write position in the buffer */
20593760b116c90f3e439552763eef632a3bbb17vboxsync /* How much space of the buffer is currently in use */
20593760b116c90f3e439552763eef632a3bbb17vboxsync /* How big is the buffer */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync /* The buffer itself */
20593760b116c90f3e439552763eef632a3bbb17vboxsync/* Pointer to an ring buffer structure */
ea9fe8748652b3e7b3f1245001f9d7cd8c9eaaccvboxsyncPPDMDRVINS gpDrvIns; //@todo handle this bad programming;
ea9fe8748652b3e7b3f1245001f9d7cd8c9eaaccvboxsyncstatic void IORingBufferCreate(PIORINGBUFFER *ppBuffer, uint32_t cSize)
20593760b116c90f3e439552763eef632a3bbb17vboxsyncstatic void IORingBufferDestroy(PIORINGBUFFER pBuffer)
20593760b116c90f3e439552763eef632a3bbb17vboxsyncDECL_FORCE_INLINE(void) IORingBufferReset(PIORINGBUFFER pBuffer)
20593760b116c90f3e439552763eef632a3bbb17vboxsyncDECL_FORCE_INLINE(uint32_t) IORingBufferFree(PIORINGBUFFER pBuffer)
20593760b116c90f3e439552763eef632a3bbb17vboxsync return pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncDECL_FORCE_INLINE(uint32_t) IORingBufferUsed(PIORINGBUFFER pBuffer)
static void IORingBufferAquireReadBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
*ppStart = 0;
*pcSize = 0;
if (uUsed > 0)
if (uSize > 0)
static void IORingBufferAquireWriteBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
*ppStart = 0;
*pcSize = 0;
if (uFree > 0)
if (uSize > 0)
//@todo need to see if they need to move to pdmifs.h
#define AUDIO_HOST_ENDIANNESS 0
int buffer_msecs_out;
int buffer_msecs_in;
typedef struct DRVAUDIOVRDE
typedef struct VRDEVoice
void * pvUserCtx;
void *rate;
void *pvSamplesBuffer;
void *pvRateBuffer;
typedef struct VRDEVoiceOut
#define PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface) ( (PDRVAUDIOVRDE)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIOVRDE, IHostAudioR3)) )
if (mpDrv)
case AUD_FMT_S8:
case AUD_FMT_U8:
case AUD_FMT_S16:
case AUD_FMT_U16:
case AUD_FMT_S32:
case AUD_FMT_U32:
int m = INT_MAX;
int nb_live = 0;
int smin;
if (!*nb_live) {
return live;
int nb_live;
int live;
return live;
return live;
return (d + incr);
return VINF_SUCCESS;
if (cbSamples == 0)
return VINF_SUCCESS;
csAvail = IORingBufferFree(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); /* bytes -> samples */
return rc;
STDMETHODIMP AudioVRDE::handleVRDESvrCmdAudioInputEventBegin(void *pvContext, int iSampleHz, int cChannels, int cBits, bool fUnsigned)
int bitIdx;
bitIdx = 0;
return VINF_SUCCESS;
* pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
void AudioVRDE::handleVRDESvrCmdAudioInputEventData(void *pvContext, const void *pvData, uint32_t cbData)
cConvertedSamples = (cSamples * pVRDEVoice->pHostVoiceIn.Props.uFrequency) / pVRDEVoice->uFrequency;
if (pConvertedSampleBuf)
if (cbSamples)
* pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
static DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut, audsettings_t *as)
return VINF_SUCCESS;
static DECLCALLBACK(int) drvAudioVRDEInitIn (PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, audsettings_t *as)
return VINF_SUCCESS;
static DECLCALLBACK(int) drvAudioVRDEPlayIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn)
char *pcSrc;
/* use this from DrvHostCoreAudio.c */
/* how much space is used in the ring buffer in pRecordedVocieBuf with pAudioVRDE . Bytes-> samples*/
LogFlow(("AudioVRDE: [Input] Start reading buffer with %d samples (%d bytes)\n", cSamplesRingBuffer,
LogFlow(("AudioVRDE: [Input] Try reading %RU32 samples (%RU32 bytes)\n", cSamplesToRead, cbToRead));
LogFlow(("AuderVRDE: [Input] There are %d samples (%d bytes) available\n", cSamplesToRead, cbToRead));
if (cSamplesToRead == 0)
return cSamplesRead;
static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
int live;
int cSamplesPlayed;
int cSamplesToSend = 0;
cSamplesPlayed = (int)((2 * ticks * pHostVoiceOut->Props.uFrequency + ticks_per_second) / ticks_per_second / 2);
if (cSamplesPlayed < 0)
LogFlow(("DrvAudioVRDE: send audio sample freq=%d, chan=%d, cBits = %d, fsigned = %d, cSamples=%d format=%d \n",
pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
/*pHostStereoSampleBuff already has the samples which exceeded its space. They have overwriten the old
format);
pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
return cSamplesToSend;
static DECLCALLBACK(void) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
static DECLCALLBACK(int) drvAudioVRDEDisableEnableOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT hw, int cmd)
return VINF_SUCCESS;
static DECLCALLBACK(int) drvAudioVRDEDisableEnableIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, int cmd)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
/* @todo check if szHostVoiceOut = sizeof VRDEVoice works. VRDEVoice doesn't contain HOSTVOICEOUT. */
return NULL;
DECLCALLBACK(int) AudioVRDE::drvAudioVRDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
void *pv;
return rc;
return rc;
* Get the interface for the above driver (DrvAudio) to make mixer/conversion calls .
return VERR_PDM_MISSING_INTERFACE_ABOVE;
return VINF_SUCCESS;
sizeof(DRVAUDIOVRDE),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,