DrvAudioVRDE.cpp revision 5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/* $Id$ */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/** @file
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * VBox Audio VRDE backend
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Copyright (C) 2006-2010 Oracle Corporation
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * available from http://www.virtualbox.org. This file is free software;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * you can redistribute it and/or modify it under the terms of the GNU
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * General Public License (GPL) as published by the Free Software
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include "DrvAudioVRDE.h"
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include "ConsoleImpl.h"
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include "ConsoleVRDPServer.h"
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include "Logging.h"
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <VBox/vmm/pdmaudioifs.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <VBox/vmm/pdmdrv.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <VBox/RemoteDesktop/VRDE.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <VBox/vmm/cfgm.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <VBox/err.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <iprt/mem.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#include <iprt/cdefs.h>
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*******************************************************************************
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * IO Ring Buffer section
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ******************************************************************************/
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/* Implementation of a lock free ring buffer which could be used in a multi
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * threaded environment. Note that only the acquire, release and getter
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * functions are threading aware. So don't use reset if the ring buffer is
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * still in use. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef struct IORINGBUFFER
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* The current read position in the buffer */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uReadPos;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* The current write position in the buffer */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uWritePos;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much space of the buffer is currently in use */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync volatile uint32_t cBufferUsed;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How big is the buffer */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cBufSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* The buffer itself */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync char *pBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync} IORINGBUFFER;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/* Pointer to an ring buffer structure */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef IORINGBUFFER* PIORINGBUFFER;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncPPDMDRVINS gpDrvIns; //@todo handle this bad programming;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic void IORingBufferCreate(PIORINGBUFFER *ppBuffer, uint32_t cSize)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PIORINGBUFFER pTmpBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(ppBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppBuffer = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pTmpBuffer = RTMemAllocZ(sizeof(IORINGBUFFER));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pTmpBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pTmpBuffer->pBuffer = RTMemAlloc(cSize);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if(pTmpBuffer->pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pTmpBuffer->cBufSize = cSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppBuffer = pTmpBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pTmpBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic void IORingBufferDestroy(PIORINGBUFFER pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pBuffer->pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pBuffer->pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(void) IORingBufferReset(PIORINGBUFFER pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pBuffer->uReadPos = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pBuffer->uWritePos = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pBuffer->cBufferUsed = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(uint32_t) IORingBufferFree(PIORINGBUFFER pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(uint32_t) IORingBufferUsed(PIORINGBUFFER pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return ASMAtomicReadU32(&pBuffer->cBufferUsed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(uint32_t) IORingBufferSize(PIORINGBUFFER pBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return pBuffer->cBufSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic void IORingBufferAquireReadBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uUsed = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uSize = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppStart = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *pcSize = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much is in use? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uUsed = ASMAtomicReadU32(&pBuffer->cBufferUsed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (uUsed > 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Get the size out of the requested size, the read block till the end
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * of the buffer & the currently used size. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uReadPos, uUsed));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (uSize > 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Return the pointer address which point to the current read
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * position. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppStart = pBuffer->pBuffer + pBuffer->uReadPos;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *pcSize = uSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(void) IORingBufferReleaseReadBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Split at the end of the buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pBuffer->uReadPos = (pBuffer->uReadPos + cSize) % pBuffer->cBufSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicSubU32(&pBuffer->cBufferUsed, cSize);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic void IORingBufferAquireWriteBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uFree;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppStart = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *pcSize = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much is free? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uFree = pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (uFree > 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Get the size out of the requested size, the write block till the end
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * of the buffer & the currently free size. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uWritePos, uFree));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (uSize > 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Return the pointer address which point to the current write
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * position. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *ppStart = pBuffer->pBuffer + pBuffer->uWritePos;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *pcSize = uSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECL_FORCE_INLINE(void) IORingBufferReleaseWriteBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertPtr(pBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Split at the end of the buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pBuffer->uWritePos = (pBuffer->uWritePos + cSize) % pBuffer->cBufSize;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicAddU32(&pBuffer->cBufferUsed, cSize);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/****************** Ring Buffer Function Ends *****************/
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync//@todo need to see if they need to move to pdmifs.h
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define AUDIO_HOST_ENDIANNESS 0
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define VOICE_ENABLE 1
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define VOICE_DISABLE 2
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/* Initialization status indicator used for the recreation of the AudioUnits. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define CA_STATUS_UNINIT UINT32_C(0) /* The device is uninitialized */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define CA_STATUS_IN_INIT UINT32_C(1) /* The device is currently initializing */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define CA_STATUS_INIT UINT32_C(2) /* The device is initialized */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define CA_STATUS_IN_UNINIT UINT32_C(3) /* The device is currently uninitializing */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync//@todo move t_sample as a PDM interface
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync//typedef struct { int mute; uint32_t r; uint32_t l; } volume_t;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define INT_MAX 0x7fffffff
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvolume_t nominal_volume = {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync 0,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync INT_MAX,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync INT_MAX
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync};
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/* The desired buffer length in milliseconds. Will be the target total stream
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * latency on newer version of pulse. Apparent latency can be less (or more.)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * In case its need to be used. Currently its not used.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#if 0
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic struct
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int buffer_msecs_out;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int buffer_msecs_in;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync} confAudioVRDE
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync=
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync INIT_FIELD (.buffer_msecs_out = ) 100,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync INIT_FIELD (.buffer_msecs_in = ) 100,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync};
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#endif
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/**
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Audio VRDE driver instance data.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @extends PDMIAUDIOSNIFFERCONNECTOR
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef struct DRVAUDIOVRDE
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /** Pointer to audio VRDE object */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AudioVRDE *pAudioVRDE;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMDRVINS pDrvIns;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /** Pointer to the driver instance structure. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMIHOSTAUDIO IHostAudioR3;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ConsoleVRDPServer *pConsoleVRDPServer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /** Pointer to the DrvAudio port interface that is above it. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMIAUDIOCONNECTOR pUpPort;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef struct PDMHOSTVOICEOUT PDMHOSTVOICEOUT;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef PDMHOSTVOICEOUT *PPDMHOSTVOICEOUT;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef struct VRDEVoice
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Audio and audio details for recording */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMHOSTVOICEIN pHostVoiceIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void * pvUserCtx;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Number of bytes per frame (bitsPerSample * channels) of the actual input format. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cBytesPerFrame;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Frequency of the actual audio format. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t uFrequency;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* If the actual format frequence differs from the requested format, this is not NULL. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void *rate;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Temporary buffer for st_sample_t representation of the input audio data. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void *pvSamplesBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* buffer for bytes of samples (not rate converted) */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbSamplesBufferAllocated;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Temporary buffer for frequency conversion. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void *pvRateBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* buffer for bytes rate converted samples */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbRateBufferAllocated;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* A ring buffer for transferring data to the playback thread */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PIORINGBUFFER pRecordedVoiceBuf;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync t_sample * convAudioDevFmtToStSampl;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t fIsInit;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t status;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync};
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef VRDEVoice *PVRDEVoice;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef struct VRDEVoiceOut
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMHOSTVOICEOUT pHostVoiceOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint64_t old_ticks;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint64_t cSamplesSentPerSec;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync};
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsynctypedef VRDEVoiceOut * PVRDEVoiceOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/** Makes a PDRVBLOCK out of a PPDMIBLOCK. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync#define PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface) ( (PDRVAUDIOVRDE)((uintptr_t)pInterface - RT_OFFSETOF(DRVAUDIOVRDE, IHostAudioR3)) )
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncAudioVRDE::AudioVRDE(Console *console)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync : mpDrv(NULL),
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync mParent(console)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncAudioVRDE::~AudioVRDE()
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (mpDrv)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync mpDrv->pAudioVRDE = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync mpDrv = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncPPDMIAUDIOCONNECTOR AudioVRDE::getDrvAudioPort()
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync Assert(mpDrv);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return mpDrv->pUpPort;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvoid AudioVRDE::handleVRDESvrCmdAudioInputIntercept(bool fIntercept)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: handleVRDPCmdInputIntercept\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void *) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("drvAudioVRDEInit \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic void drvAudioVRDEPcmInitInfo(PDMPCMPROPERTIES * pProps, audsettings_t *as)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int bits = 8, sign = 0, shift = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: PcmInitInfo \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync switch (as->fmt) {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_S8:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync sign = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_U8:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync break;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_S16:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync sign = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_U16:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync bits = 16;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync shift = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync break;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_S32:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync sign = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync case AUD_FMT_U32:
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync bits = 32;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync shift = 2;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync break;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->uFrequency = as->freq;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->cBits = bits;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->fSigned = sign;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->cChannels = as->nchannels;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->cShift = (as->nchannels == 2) + shift;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->fAlign = (1 << pProps->cShift) - 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->cbPerSec = pProps->uFrequency << pProps->cShift;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pProps->fSwapEndian = (as->endianness != AUDIO_HOST_ENDIANNESS);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Hard voice (playback)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic int audio_pcm_hw_find_min_out (PPDMHOSTVOICEOUT hw, int *nb_livep)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMGSTVOICEOUT sw;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMGSTVOICEOUT pIter;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int m = INT_MAX;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int nb_live = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("Hard Voice Playback \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTListForEach(&hw->HeadGstVoiceOut, pIter, PDMGSTVOICEOUT, ListGstVoiceOut)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync sw = pIter;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (sw->State.fActive || !sw->State.fEmpty)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync m = audio_MIN (m, sw->cSamplesMixed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync nb_live += 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *nb_livep = nb_live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return m;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncint audio_pcm_hw_get_live_out2 (PPDMHOSTVOICEOUT hw, int *nb_live)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int smin;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync smin = audio_pcm_hw_find_min_out (hw, nb_live);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (!*nb_live) {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int live = smin;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (live < 0 || live > hw->cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncint audio_pcm_hw_get_live_out (PPDMHOSTVOICEOUT hw)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int nb_live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (live < 0 || live > hw->cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Hard voice (capture)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic int audio_pcm_hw_find_min_in (PPDMHOSTVOICEIN hw)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMGSTVOICEIN pIter;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int m = hw->cSamplesCaptured;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTListForEach(&hw->HeadGstVoiceIn, pIter, PDMGSTVOICEIN, ListGstVoiceIn)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pIter->State.fActive)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync m = audio_MIN (m, pIter->cHostSamplesAcquired);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return m;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncint audio_pcm_hw_get_live_in (PPDMHOSTVOICEIN hw)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int live = hw->cSamplesCaptured - audio_pcm_hw_find_min_in (hw);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (live < 0 || live > hw->cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic inline void *advance (void *p, int incr)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint8_t *d = (uint8_t*)p;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return (d + incr);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncuint64_t audio_get_ticks_per_sec (void)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return PDMDrvHlpTMGetVirtualFreq (gpDrvIns);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncuint64_t audio_get_clock (void)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return PDMDrvHlpTMGetVirtualTime (gpDrvIns);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvoid VRDEReallocSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cbBuffer > pVRDEVoice->cbSamplesBufferAllocated)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->pvSamplesBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pVRDEVoice->pvSamplesBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvSamplesBuffer = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvSamplesBuffer = RTMemAlloc(cbBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->pvSamplesBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbSamplesBufferAllocated = cbBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbSamplesBufferAllocated = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvoid VRDEReallocRateAdjSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cbBuffer > pVRDEVoice->cbRateBufferAllocated)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pVRDEVoice->pvRateBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvRateBuffer = RTMemAlloc(cbBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->pvRateBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbRateBufferAllocated = cbBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbRateBufferAllocated = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*******************************************************************************
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * AudioVRDE input section
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ******************************************************************************/
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Callback to feed audio input buffer. Samples format is be the same as
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * in the voice. The caller prepares st_sample_t.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @param cbSamples Size of pvSamples array in bytes.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @param pvSamples Points to an array of samples.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @return IPRT status code.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic int fltRecordingCallback(PVRDEVoice pVRDEVoice, uint32_t cbSamples, const void *pvSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int rc = VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t csAvail = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t csToWrite = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbToWrite = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t csWritten = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync char *pcDst = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("audio-filter: fltRecordingCallback\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync Assert((cbSamples % sizeof(PDMHOSTSTEREOSAMPLE)) == 0);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (!pVRDEVoice->fIsInit)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* If nothing is pending return immediately. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cbSamples == 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much space is free in the ring buffer? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMHOSTSTEREOSAMPLE psSrc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csAvail = IORingBufferFree(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); /* bytes -> samples */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much space is used in the audio buffer. Use the smaller size of the too. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csAvail = RT_MIN(csAvail, cbSamples / sizeof(PDMHOSTSTEREOSAMPLE));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Iterate as long as data is available */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync while(csWritten < csAvail)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much is left? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csToWrite = csAvail - csWritten;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cbToWrite = csToWrite * sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Try to acquire the necessary space from the ring buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferAquireWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite, &pcDst, &cbToWrite);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much do we get? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csToWrite = cbToWrite / sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Break if nothing is free anymore. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (RT_UNLIKELY(csToWrite == 0))
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync break;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Copy the data from the audio buffer to the ring buffer in PVRDEVoice. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync memcpy(pcDst, (uint8_t *)pvSamples + (csWritten * sizeof(PDMHOSTSTEREOSAMPLE)), cbToWrite);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Release the ring buffer, so the main thread could start reading this data. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferReleaseWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csWritten += csToWrite;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: [Input] Finished writing buffer with %RU32 samples (%RU32 bytes)\n",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync csWritten, csWritten * sizeof(PDMHOSTSTEREOSAMPLE)));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return rc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncSTDMETHODIMP AudioVRDE::handleVRDESvrCmdAudioInputEventBegin(void *pvContext, int iSampleHz, int cChannels, int cBits, bool fUnsigned)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int bitIdx;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: handleVRDPCmdInputEventBegin\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Prepare a format convertion for the actually used format. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cBytesPerFrame = ((cBits + 7) / 8) * cChannels;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cBits == 16)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync bitIdx = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else if (cBits == 32)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync bitIdx = 2;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync bitIdx = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync //PPDMIAUDIOCONNECTOR pPort = server->mConsole->getAudioVRDE()->getDrvAudioPort();
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Call DrvAudio interface to get the t_sample type conversion function */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->convAudioDevFmtToStSampl = mpDrv->pUpPort->pfnConvDevFmtToStSample(mpDrv->pUpPort,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync (cChannels == 2) ? 1 : 0,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync !fUnsigned, 0, bitIdx
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync );
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->convAudioDevFmtToStSampl)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: Failed to get the conversion function \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: Required freq as requested by VRDP Server = %d\n", iSampleHz));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync //if (iSampleHz && iSampleHz != pVRDEVoice->pHostVoiceIn.Props.uFrequency)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* @todo if the above condition is false then pVRDEVoice->uFrequency will remain 0 */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->rate = mpDrv->pUpPort->pfnPrepareAudioConversion(mpDrv->pUpPort, iSampleHz,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pHostVoiceIn.Props.uFrequency);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->uFrequency = iSampleHz;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: pVRDEVoice assigned requested freq =%d\n", pVRDEVoice->uFrequency));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvoid AudioVRDE::handleVRDESvrCmdAudioInputEventData(void *pvContext, const void *pvData, uint32_t cbData)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMHOSTSTEREOSAMPLE pHostStereoSampleBuf; /* target sample buffer */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMHOSTSTEREOSAMPLE pConvertedSampleBuf; /* samples adjusted for rate */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSamples = cbData / pVRDEVoice->cBytesPerFrame; /* Count of samples */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void * pTmpSampleBuf = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cConvertedSamples; /* samples adjusted for rate */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbSamples; /* count of bytes occupied by samples */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t rc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: handleVRDPCmdInputEventData cbData = %d, bytesperfram=%d\n",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cbData, pVRDEVoice->cBytesPerFrame));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync VRDEReallocSampleBuf(pVRDEVoice, cSamples);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostStereoSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvSamplesBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->convAudioDevFmtToStSampl(pHostStereoSampleBuf, pvData, cSamples, &nominal_volume);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* count of rate adjusted samples */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->uFrequency = 22100; /* @todo handle this. How pVRDEVoice will get proper value */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cConvertedSamples = (cSamples * pVRDEVoice->pHostVoiceIn.Props.uFrequency) / pVRDEVoice->uFrequency;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync VRDEReallocRateAdjSampleBuf(pVRDEVoice, cConvertedSamples);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pConvertedSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvRateBuffer;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pConvertedSampleBuf)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSampleSrc = cSamples;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSampleDst = cConvertedSamples;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync mpDrv->pUpPort->pfnDoRateConversion(mpDrv->pUpPort, pVRDEVoice->rate, pHostStereoSampleBuf,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pConvertedSampleBuf, &cSampleSrc, &cConvertedSamples);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pTmpSampleBuf = pConvertedSampleBuf;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cbSamples = cConvertedSamples * sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cbSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync rc = fltRecordingCallback(pVRDEVoice, cbSamples, pTmpSampleBuf);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncvoid AudioVRDE::handleVRDESvrCmdAudioInputEventEnd(void *pvContext)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: handleVRDPCmdInputEventEnd\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* The caller will not use this context anymore. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->rate)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync mpDrv->pUpPort->pfnEndAudioConversion(mpDrv->pUpPort, pVRDEVoice->rate);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pVRDEVoice->pvSamplesBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pVRDEVoice->pvSamplesBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvSamplesBuffer = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if(pVRDEVoice->pvRateBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync RTMemFree(pVRDEVoice->pvRateBuffer);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvRateBuffer = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut, audsettings_t *as)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDEInitOut: audio input begin cShift=%d\n", pHostVoiceOut->Props.cShift));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->cSamples = 6174;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync drvAudioVRDEPcmInitInfo(&pVRDEVoiceOut->pHostVoiceOut.Props, as);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEInitIn (PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, audsettings_t *as)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: drvAudioVRDEInitIn \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceIn->cSamples = 6174;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync drvAudioVRDEPcmInitInfo(&pVRDEVoice->pHostVoiceIn.Props, as);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEPlayIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbAvlblRingBuffer = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSamplesRingBuffer = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSamplesToRead = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cSamplesRead = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint32_t cbToRead;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync char *pcSrc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMHOSTSTEREOSAMPLE * psDst;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync //@todo take care of the size of the buffer allocated to pHostVoiceIn
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: drvAudioVRDEPlayIn \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* use this from DrvHostCoreAudio.c */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (ASMAtomicReadU32(&pVRDEVoice->status) != CA_STATUS_INIT)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: VRDE voice not initialized \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* how much space is used in the ring buffer in pRecordedVocieBuf with pAudioVRDE . Bytes-> samples*/
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesRingBuffer = IORingBufferUsed(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much space is available in the mix buffer. Use the smaller size of the too. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesRingBuffer = RT_MIN(cSamplesRingBuffer, (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples -
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync audio_pcm_hw_get_live_in (&pVRDEVoice->pHostVoiceIn)));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: [Input] Start reading buffer with %d samples (%d bytes)\n", cSamplesRingBuffer,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesRingBuffer * sizeof(PDMHOSTSTEREOSAMPLE)));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Iterate as long as data is available */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync while (cSamplesRead < cSamplesRingBuffer)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much is left? Split request at the end of our samples buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesToRead = RT_MIN(cSamplesRingBuffer - cSamplesRead,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples - pVRDEVoice->pHostVoiceIn.offWrite));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cbToRead = cSamplesToRead * sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: [Input] Try reading %RU32 samples (%RU32 bytes)\n", cSamplesToRead, cbToRead));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Try to acquire the necessary block from the ring buffer. Remeber in fltRecrodCallback we
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * we are filling this buffer with the audio data available from VRDP. Here we are reading it
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /*todo do I need to introduce a thread to fill the buffer in fltRecordcallback. So that
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * filling is in separate thread and the reading of that buffer is in separate thread
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferAquireReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead, &pcSrc, &cbToRead);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much to we get? */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesToRead = cbToRead / sizeof(PDMHOSTSTEREOSAMPLE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AuderVRDE: [Input] There are %d samples (%d bytes) available\n", cSamplesToRead, cbToRead));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Break if nothing is used anymore. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cSamplesToRead == 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: Nothing to read \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync break;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Copy the data from our ring buffer to the mix buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync psDst = pVRDEVoice->pHostVoiceIn.pConversionBuf + pVRDEVoice->pHostVoiceIn.offWrite;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync memcpy(psDst, pcSrc, cbToRead);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Release the read buffer, so it could be used for new data. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferReleaseReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pHostVoiceIn.offWrite = (pVRDEVoice->pHostVoiceIn.offWrite + cSamplesToRead)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync % pVRDEVoice->pHostVoiceIn.cSamples;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* How much have we reads so far. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesRead += cSamplesToRead;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("AudioVRDE: [Input] Finished reading buffer with %d samples (%d bytes)\n",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesRead, cSamplesRead * sizeof(PDMHOSTSTEREOSAMPLE)));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return cSamplesRead;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint8_t *pu8Dst;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int cSamplesPlayed;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int cSamplesToSend = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Just call the VRDP server with the data.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync live = audio_pcm_hw_get_live_out (pHostVoiceOut);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint64_t now = audio_get_clock();
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint64_t ticks = now - pVRDEVoiceOut->old_ticks;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync uint64_t ticks_per_second = audio_get_ticks_per_sec();
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesPlayed = (int)((2 * ticks * pHostVoiceOut->Props.uFrequency + ticks_per_second) / ticks_per_second / 2);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cSamplesPlayed < 0)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesPlayed = live;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->Props.cBits = 128;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHostVoiceOut->Props.uFrequency,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->Props.cChannels,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->Props.cBits, /* bits per sample */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync !pHostVoiceOut->Props.fSigned);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: send audio sample freq=%d, chan=%d, cBits = %d, fsigned = %d, cSamples=%d format=%d \n",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->Props.uFrequency, pHostVoiceOut->Props.cChannels,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->Props.cBits, pHostVoiceOut->Props.fSigned,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->cSamples, format)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync );
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoiceOut->old_ticks = now;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesToSend = RT_MIN(live, cSamplesPlayed);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (pHostVoiceOut->offRead + cSamplesToSend > pHostVoiceOut->cSamples)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* send the samples till the end of pHostStereoSampleBuf */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync (pHostVoiceOut->cSamples - pHostVoiceOut->offRead), format);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /*pHostStereoSampleBuff already has the samples which exceeded its space. They have overwriten the old
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * played sampled starting from offset 0. So based on the number of samples that we had to play,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * read the number of samples from offset 0 .
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[0],
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync (cSamplesToSend - (pHostVoiceOut->cSamples -
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->offRead)),
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync format);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync cSamplesToSend, format);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceOut->offRead = (pHostVoiceOut->offRead + cSamplesToSend) % pHostVoiceOut->cSamples;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return cSamplesToSend;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN hw)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: drvAudioVRDEFiniIn \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: audio input end\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEDisableEnableOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT hw, int cmd)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableOut \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(int) drvAudioVRDEDisableEnableIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, int cmd)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pDrv = PDMIHOSTAUDIO_2_DRVAUDIOVRDE(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Initialize VRDEVoice and return to VRDP server which returns this struct back to us
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * in the form void * pvContext
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableIn \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* initialize only if not already done */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (cmd == VOICE_ENABLE)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync //@todo if (!pVRDEVoice->fIsInit)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync // IORingBufferReset(pVRDEVoice->pRecordedVoiceBuf);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: Intializing the VRDE params and buffer \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->fIsInit = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pHostVoiceIn = *pHostVoiceIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cBytesPerFrame =1 ;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->uFrequency = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->rate = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbSamplesBufferAllocated = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pvRateBuffer = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->cbRateBufferAllocated = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pHostVoiceIn.cSamples = 2048;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Initialize the hardware info section with the audio settings */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_INIT);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Create the internal ring buffer. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferCreate(&pVRDEVoice->pRecordedVoiceBuf,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pHostVoiceIn.cSamples * sizeof(PDMHOSTSTEREOSAMPLE));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (!RT_VALID_PTR(pVRDEVoice->pRecordedVoiceBuf))
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogRel(("AudioVRDE: [Input] Failed to create internal ring buffer\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VERR_NO_MEMORY;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_INIT);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEVoice, pHostVoiceIn->cSamples,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceIn->Props.uFrequency,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pHostVoiceIn->Props.cChannels, pHostVoiceIn->Props.cBits);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync else if (cmd == VOICE_DISABLE)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("DrvAudioVRDE: Cmd to disable VRDE \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->fIsInit = 0;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_UNINIT);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync IORingBufferDestroy(pVRDEVoice->pRecordedVoiceBuf);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pVRDEVoice->pRecordedVoiceBuf = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_UNINIT);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void) drvAudioVRDEGetConf(PPDMIBASE pInterface, PPDMAUDIOCONF pAudioConf)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogFlow(("drvAudioVRDE: drvAudioVRDEGetConf \n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* @todo check if szHostVoiceOut = sizeof VRDEVoice works. VRDEVoice doesn't contain HOSTVOICEOUT. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pAudioConf->szHostVoiceOut = sizeof(VRDEVoice);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pAudioConf->szHostVoiceIn = sizeof(VRDEVoice);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pAudioConf->MaxHostVoicesOut = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pAudioConf->MaxHostVoicesIn = 1;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/**
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void *) drvAudioVRDEQueryInterface(PPDMIBASE pInterface, const char *pszIID)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudioR3);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncstatic DECLCALLBACK(void) drvAudioVRDEDestruct(PPDMDRVINS pDrvIns)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/**
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Construct a DirectSound Audio driver instance.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync *
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * @copydoc FNPDMDRVCONSTRUCT
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncDECLCALLBACK(int) AudioVRDE::drvAudioVRDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync LogRel(("drvAudioVRDEConstruct\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* we save the address of AudioVRDE in Object node in CFGM tree and address of VRDP server in
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * ObjectVRDPServer node. So presence of both is necessary.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync //if (!CFGMR3AreValuesValid(pCfg, "Object\0") || !CFGMR3AreValuesValid(pCfg, "ObjectVRDPServer\0"))
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync // return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ("Configuration error: Not possible to attach anything to this driver!\n"),
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync VERR_PDM_DRVINS_NO_ATTACH);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Init the static parts.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->pDrvIns = pDrvIns;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync gpDrvIns = pDrvIns;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* IBase */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnInitIn = drvAudioVRDEInitIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnInitOut = drvAudioVRDEInitOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnDisableEnableOut = drvAudioVRDEDisableEnableOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnDisableEnableIn = drvAudioVRDEDisableEnableIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnFiniIn = drvAudioVRDEFiniIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnFiniOut = drvAudioVRDEFiniOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnPlayIn = drvAudioVRDEPlayIn;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnPlayOut = drvAudioVRDEPlayOut;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnGetConf = drvAudioVRDEGetConf;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->IHostAudioR3.pfnInit = drvAudioVRDEInit;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* Get VRDPServer pointer */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync void *pv;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pv);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (RT_FAILURE(rc))
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return rc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pv;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pv = NULL;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (RT_FAILURE(rc))
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return rc;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->pAudioVRDE = (AudioVRDE *)pv;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->pAudioVRDE->mpDrv = pThis;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /*
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls .
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Described in CFGM tree.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync if (!pThis->pUpPort)
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync {
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AssertMsgFailed(("Configuration error: No Audio Sniffer port interface above!\n"));
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VERR_PDM_MISSING_INTERFACE_ABOVE;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync }
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync return VINF_SUCCESS;
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync}
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync/**
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync * Char driver registration record.
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsyncconst PDMDRVREG g_DrvAudioVRDE =
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync{
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDM_DRVREG_VERSION,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* szName */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync "AudioVRDE",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* szRCMod */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync "",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* szR0Mod */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync "",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pszDescription */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync "Audio VRDE",
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* fFlags */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* fClass. */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDM_DRVREG_CLASS_AUDIO,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* cMaxInstances */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync ~0U,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* cbInstance */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync sizeof(DRVAUDIOVRDE),
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnConstruct */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync AudioVRDE::drvAudioVRDEConstruct,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnDestruct */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync drvAudioVRDEDestruct,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnRelocate */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnIOCtl */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnPowerOn */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnReset */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnSuspend */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnResume */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnAttach */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnDetach */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnPowerOff */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* pfnSoftReset */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync NULL,
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync /* u32EndVersion */
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync PDM_DRVREG_VERSION
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync};
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync
5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7vboxsync