VirtualBox

Changeset 53442 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Dec 4, 2014 1:49:43 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
97155
Message:

PDM Audio: Branch -> trunk.

Location:
trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/VBox

  • trunk/src/VBox/Main/src-client/AudioSnifferInterface.cpp

    r51612 r53442  
    2626#include <VBox/vmm/cfgm.h>
    2727#include <VBox/err.h>
     28
     29#ifdef LOG_GROUP
     30 #undef LOG_GROUP
     31#endif
     32#define LOG_GROUP LOG_GROUP_DEV_AUDIO
     33#include <VBox/log.h>
    2834
    2935//
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r53407 r53442  
    414414    , mpVmm2UserMethods(NULL)
    415415    , m_pVMMDev(NULL)
    416 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER
     416#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     417    , mAudioVRDE(NULL)
     418#else
    417419    , mAudioSniffer(NULL)
    418420#endif
     
    596598#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    597599        unconst(mAudioVRDE) = new AudioVRDE(this);
    598         AssertComRCReturnRC(rc);
     600        AssertReturn(mAudioVRDE, E_FAIL);
    599601#else
    600602        unconst(mAudioSniffer) = new AudioSniffer(this);
    601603        AssertReturn(mAudioSniffer, E_FAIL);
    602604#endif
    603 
    604605        FirmwareType_T enmFirmwareType;
    605606        mMachine->COMGETTER(FirmwareType)(&enmFirmwareType);
     
    730731    }
    731732#endif
    732 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER
     733
     734#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     735    if (mAudioVRDE)
     736    {
     737        delete mAudioVRDE;
     738        unconst(mAudioVRDE) = NULL;
     739    }
     740#else
    733741    if (mAudioSniffer)
    734742    {
     
    14331441    if (fu32Intercepted & VRDE_CLIENT_INTERCEPT_AUDIO)
    14341442    {
     1443#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     1444        if (mAudioVRDE)
     1445            mAudioVRDE->onVRDEInputIntercept(false /* fIntercept */);
     1446#else
    14351447        mcAudioRefs--;
    14361448
    14371449        if (mcAudioRefs <= 0)
    14381450        {
    1439 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER
    14401451            if (mAudioSniffer)
    14411452            {
    14421453                PPDMIAUDIOSNIFFERPORT port = mAudioSniffer->getAudioSnifferPort();
    14431454                if (port)
    1444                 {
    14451455                    port->pfnSetup(port, false, false);
    1446                 }
    14471456            }
     1457        }
    14481458#endif
    1449         }
    14501459    }
    14511460
     
    14801489    AutoCaller autoCaller(this);
    14811490    AssertComRCReturnVoid(autoCaller.rc());
    1482 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER
    1483     LogFlowFunc(("mAudioSniffer %p, u32ClientId %d.\n",
    1484                  mAudioSniffer, u32ClientId));
    1485     NOREF(u32ClientId);
    1486 #endif
    1487 
     1491
     1492    LogFlowFunc(("u32ClientId=%RU32\n", u32ClientId));
     1493
     1494#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     1495    if (mAudioVRDE)
     1496        mAudioVRDE->onVRDEInputIntercept(true /* fIntercept */);
     1497#else
    14881498    ++mcAudioRefs;
    14891499
    14901500    if (mcAudioRefs == 1)
    14911501    {
    1492 #ifndef VBOX_WITH_PDM_AUDIO_DRIVER
    14931502        if (mAudioSniffer)
    14941503        {
    14951504            PPDMIAUDIOSNIFFERPORT port = mAudioSniffer->getAudioSnifferPort();
    14961505            if (port)
    1497             {
    14981506                port->pfnSetup(port, true, true);
    1499             }
    1500         }
     1507        }
     1508    }
    15011509#endif
    1502     }
    15031510
    15041511    LogFlowFuncLeave();
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r53407 r53442  
    26122612        InsertConfigInteger(pCfg,  "Object", (uintptr_t)pAudioSniffer);
    26132613#endif
    2614 
    26152614        /*
    2616          * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio
     2615         * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio.
    26172616         */
    26182617        BOOL fAudioEnabled = FALSE;
     
    26302629                case AudioControllerType_AC97:
    26312630                {
    2632                     /* default: ICH AC97 */
     2631                    /* Default: ICH AC97. */
    26332632                    InsertConfigNode(pDevices, "ichac97", &pDev);
    26342633                    InsertConfigNode(pDev,     "0", &pInst);
     
    26402639                case AudioControllerType_SB16:
    26412640                {
    2642                     /* legacy SoundBlaster16 */
     2641                    /* Legacy SoundBlaster16. */
    26432642                    InsertConfigNode(pDevices, "sb16", &pDev);
    26442643                    InsertConfigNode(pDev,     "0", &pInst);
     
    26542653                case AudioControllerType_HDA:
    26552654                {
    2656                     /* Intel HD Audio */
     2655                    /* Intel HD Audio. */
    26572656                    InsertConfigNode(pDevices, "hda", &pDev);
    26582657                    InsertConfigNode(pDev,     "0", &pInst);
     
    26632662            }
    26642663
    2665             /* the Audio driver */
     2664            /* The audio driver. */
    26662665            InsertConfigNode(pInst,    "LUN#0", &pLunL0);
    26672666            InsertConfigString(pLunL0, "Driver", "AUDIO");
     2667            InsertConfigNode(pLunL0,   "Config", &pCfg);
    26682668
    26692669#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2670            PCFGMNODE pLunL1;
    26702671            InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
    2671             InsertConfigString(pLunL1, "Driver", "PulseAudio");
     2672            InsertConfigNode(pLunL1, "Config", &pCfg);
    26722673#endif
    2673 
    2674             InsertConfigNode(pLunL0,   "Config", &pCfg);
    2675 
    26762674            AudioDriverType_T audioDriver;
    26772675            hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver);                       H();
     
    26802678                case AudioDriverType_Null:
    26812679                {
     2680#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2681                    InsertConfigString(pLunL1, "Driver", "NullAudio");
     2682#else
    26822683                    InsertConfigString(pCfg, "AudioDriver", "null");
     2684#endif
    26832685                    break;
    26842686                }
    26852687#ifdef RT_OS_WINDOWS
    2686 #ifdef VBOX_WITH_WINMM
     2688# ifdef VBOX_WITH_WINMM
    26872689                case AudioDriverType_WinMM:
    26882690                {
     2691#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2692                    #error "Port WinMM audio backend!" /** @todo Still needed? */
     2693#else
    26892694                    InsertConfigString(pCfg, "AudioDriver", "winmm");
     2695#endif
    26902696                    break;
    26912697                }
    2692 #endif
     2698# endif
    26932699                case AudioDriverType_DirectSound:
    26942700                {
    26952701#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    2696                     InsertConfigString(pCfg, "AudioDriver", "DSoundAudio");
     2702                    InsertConfigString(pLunL1, "Driver", "DSoundAudio");
    26972703#else
    26982704                    InsertConfigString(pCfg, "AudioDriver", "dsound");
     
    27042710                case AudioDriverType_SolAudio:
    27052711                {
     2712#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2713                    #error "Port Solaris audio backend!" /** @todo Port Solaris driver. */
     2714#else
    27062715                    InsertConfigString(pCfg, "AudioDriver", "solaudio");
    2707                     break;
    2708                 }
    2709 #endif
    2710 #ifdef RT_OS_LINUX
    2711 # ifdef VBOX_WITH_ALSA
    2712                 case AudioDriverType_ALSA:
    2713                 {
    2714 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    2715                     InsertConfigString(pCfg, "AudioDriver", "AlsaAudio");
    2716 #else
    2717                     InsertConfigString(pCfg, "AudioDriver", "alsa");
    27182716#endif
    27192717                    break;
    27202718                }
     2719#endif
     2720#ifdef VBOX_WITH_ALSA
     2721                case AudioDriverType_ALSA:
     2722                {
     2723# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2724                    InsertConfigString(pLunL1, "Driver", "AlsaAudio");
     2725# else
     2726                    InsertConfigString(pCfg, "AudioDriver", "alsa");
    27212727# endif
    2722 # ifdef VBOX_WITH_PULSE
     2728                    break;
     2729                }
     2730#endif
     2731#ifdef VBOX_WITH_PULSE
    27232732                case AudioDriverType_Pulse:
    27242733                {
    2725 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    2726                     InsertConfigString(pCfg, "AudioDriver", "PulseAudio");
    2727 #else
     2734# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2735                    InsertConfigString(pLunL1, "Driver", "PulseAudio");
     2736# else
    27282737                    InsertConfigString(pCfg, "AudioDriver", "pulse");
     2738# endif
     2739                    break;
     2740                }
    27292741#endif
    2730                     break;
    2731                 }
    2732 # endif
    2733 #endif /* RT_OS_LINUX */
    27342742#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
    27352743                case AudioDriverType_OSS:
    27362744                {
    2737                     InsertConfigString(pCfg, "AudioDriver", "oss");
     2745# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2746                    #error "Port OSS audio backend!" /** @todo Port OSS driver. */
     2747# else
     2748                    InsertConfigString(pCfg, "AudioDriver", "ossaudio");
     2749# endif
    27382750                    break;
    27392751                }
    2740 #endif
    2741 #ifdef RT_OS_FREEBSD
    2742 # ifdef VBOX_WITH_PULSE
    2743                 case AudioDriverType_Pulse:
    2744                 {
    2745 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    2746                     InsertConfigString(pCfg, "AudioDriver", "PulseAudio");
    2747 #else
    2748                     InsertConfigString(pCfg, "AudioDriver", "pulse");
    2749 #endif
    2750                     break;
    2751                 }
    2752 # endif
    27532752#endif
    27542753#ifdef RT_OS_DARWIN
    27552754                case AudioDriverType_CoreAudio:
    27562755                {
     2756# ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     2757                    InsertConfigString(pLunL1, "Driver", "CoreAudio");
     2758# else
    27572759                    InsertConfigString(pCfg, "AudioDriver", "coreaudio");
     2760# endif
    27582761                    break;
    27592762                }
    27602763#endif
    27612764            }
     2765
    27622766            hrc = pMachine->COMGETTER(Name)(bstr.asOutParam());                             H();
    2763             InsertConfigString(pCfg, "StreamName", bstr);
     2767
    27642768#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    2765             /* the Audio driver */
    2766             InsertConfigNode(pInst, "LUN#1", &pLunL0);
    2767             InsertConfigString(pLunL0, "Driver", "AUDIO");
    2768             InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
     2769            /*
     2770             * The VRDE audio backend driver. This one always is there
     2771             * and therefore is hardcoded here.
     2772             */
     2773            InsertConfigNode(pInst, "LUN#1", &pLunL1);
     2774            InsertConfigString(pLunL1, "Driver", "AUDIO");
     2775
     2776            InsertConfigNode(pLunL1, "AttachedDriver", &pLunL1);
    27692777            InsertConfigString(pLunL1, "Driver", "AudioVRDE");
    2770             InsertConfigNode(pLunL0, "Config", &pCfg);
     2778
     2779            InsertConfigNode(pLunL1, "Config", &pCfg);
    27712780            InsertConfigString(pCfg, "AudioDriver", "AudioVRDE");
    27722781            InsertConfigString(pCfg, "StreamName", bstr);
    2773             InsertConfigNode(pLunL1, "Config", &pCfg);
    2774             InsertConfigInteger(pCfg,  "Object", (uintptr_t)mAudioVRDE);
    2775             InsertConfigInteger(pCfg,  "ObjectVRDPServer", (uintptr_t)mConsoleVRDPServer);
    2776 
     2782            InsertConfigInteger(pCfg, "Object", (uintptr_t)mAudioVRDE);
     2783            InsertConfigInteger(pCfg, "ObjectVRDPServer", (uintptr_t)mConsoleVRDPServer);
     2784
     2785            /** @todo Add audio video recording driver here. */
    27772786#endif
    27782787        }
  • trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp

    r52978 r53442  
    946946                                                                   uint32_t fu32Intercepted)
    947947{
    948     ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback);
    949 
    950     server->mConsole->i_VRDPClientDisconnect(u32ClientId, fu32Intercepted);
    951 
    952     if (ASMAtomicReadU32(&server->mu32AudioInputClientId) == u32ClientId)
    953     {
    954         Log(("AUDIOIN: disconnected client %u\n", u32ClientId));
    955         ASMAtomicWriteU32(&server->mu32AudioInputClientId, 0);
     948    ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback);
     949    AssertPtrReturnVoid(pServer);
     950
     951    pServer->mConsole->i_VRDPClientDisconnect(u32ClientId, fu32Intercepted);
     952
     953    if (ASMAtomicReadU32(&pServer->mu32AudioInputClientId) == u32ClientId)
     954    {
     955        LogFunc(("Disconnected client %u\n", u32ClientId));
     956        ASMAtomicWriteU32(&pServer->mu32AudioInputClientId, 0);
    956957
    957958#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    958         server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputIntercept(false);
     959        pServer->mConsole->i_getAudioVRDE()->onVRDEInputIntercept(false);
    959960#else
    960         PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
     961        PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
    961962        if (pPort)
    962963        {
     
    970971    }
    971972
    972     int c = ASMAtomicDecS32(&server->mcClients);
    973     if (c == 0)
     973    int32_t cClients = ASMAtomicDecS32(&pServer->mcClients);
     974    if (cClients == 0)
    974975    {
    975976        /* Features which should be enabled only if there is a client. */
    976         server->remote3DRedirect(false);
     977        pServer->remote3DRedirect(false);
    977978    }
    978979}
     
    981982                                                           void **ppvIntercept)
    982983{
    983     ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback);
     984    ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback);
    984985
    985986    LogFlowFunc(("%x\n", fu32Intercept));
     
    991992        case VRDE_CLIENT_INTERCEPT_AUDIO:
    992993        {
    993             server->mConsole->i_VRDPInterceptAudio(u32ClientId);
     994            pServer->mConsole->i_VRDPInterceptAudio(u32ClientId);
    994995            if (ppvIntercept)
    995996            {
    996                 *ppvIntercept = server;
     997                *ppvIntercept = pServer;
    997998            }
    998999            rc = VINF_SUCCESS;
     
    10011002        case VRDE_CLIENT_INTERCEPT_USB:
    10021003        {
    1003             server->mConsole->i_VRDPInterceptUSB(u32ClientId, ppvIntercept);
     1004            pServer->mConsole->i_VRDPInterceptUSB(u32ClientId, ppvIntercept);
    10041005            rc = VINF_SUCCESS;
    10051006        } break;
     
    10071008        case VRDE_CLIENT_INTERCEPT_CLIPBOARD:
    10081009        {
    1009             server->mConsole->i_VRDPInterceptClipboard(u32ClientId);
     1010            pServer->mConsole->i_VRDPInterceptClipboard(u32ClientId);
    10101011            if (ppvIntercept)
    10111012            {
    1012                 *ppvIntercept = server;
     1013                *ppvIntercept = pServer;
    10131014            }
    10141015            rc = VINF_SUCCESS;
     
    10201021             * Only one client is allowed to intercept audio input.
    10211022             */
    1022             if (ASMAtomicCmpXchgU32(&server->mu32AudioInputClientId, u32ClientId, 0) == true)
    1023             {
    1024                 Log(("AUDIOIN: connected client %u\n", u32ClientId));
     1023            if (ASMAtomicCmpXchgU32(&pServer->mu32AudioInputClientId, u32ClientId, 0) == true)
     1024            {
     1025                LogFunc(("Connected client %u\n", u32ClientId));
    10251026#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    1026                 server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputIntercept(true);
     1027                pServer->mConsole->i_getAudioVRDE()->onVRDEInputIntercept(true);
    10271028#else
    1028                 PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
     1029                PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
    10291030                if (pPort)
    10301031                {
    10311032                     pPort->pfnAudioInputIntercept(pPort, true);
    10321033                     if (ppvIntercept)
    1033                      {
    1034                          *ppvIntercept = server;
    1035                      }
     1034                         *ppvIntercept = pServer;
    10361035                }
    10371036                else
    10381037                {
    10391038                    AssertFailed();
    1040                     ASMAtomicWriteU32(&server->mu32AudioInputClientId, 0);
     1039                    ASMAtomicWriteU32(&pServer->mu32AudioInputClientId, 0);
    10411040                    rc = VERR_NOT_SUPPORTED;
    10421041                }
     
    10451044            else
    10461045            {
    1047                 Log(("AUDIOIN: ignored client %u, active client %u\n", u32ClientId, server->mu32AudioInputClientId));
     1046                Log(("AUDIOIN: ignored client %u, active client %u\n", u32ClientId, pServer->mu32AudioInputClientId));
    10481047                rc = VERR_NOT_SUPPORTED;
    10491048            }
     
    13061305                                                          uint32_t cbData)
    13071306{
    1308     ConsoleVRDPServer *server = static_cast<ConsoleVRDPServer*>(pvCallback);
     1307    ConsoleVRDPServer *pServer = static_cast<ConsoleVRDPServer*>(pvCallback);
     1308    AssertPtrReturnVoid(pServer);
    13091309#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
    1310     PPDMIAUDIOSNIFFERPORT pPort = server->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
     1310    PPDMIAUDIOSNIFFERPORT pPort = pServer->mConsole->i_getAudioSniffer()->getAudioSnifferPort();
    13111311#endif
    13121312
     
    13151315        case VRDE_AUDIOIN_BEGIN:
    13161316        {
     1317#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
     1318            pServer->mConsole->i_getAudioVRDE()->onVRDEInputBegin(pvCtx, (PVRDEAUDIOINBEGIN)pvData);
     1319#else
    13171320            const VRDEAUDIOINBEGIN *pParms = (const VRDEAUDIOINBEGIN *)pvData;
    1318 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    1319             server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventBegin(pvCtx,
    1320                                                                                    VRDE_AUDIO_FMT_SAMPLE_FREQ(pParms->fmt),
    1321                                                                                    VRDE_AUDIO_FMT_CHANNELS(pParms->fmt),
    1322                                                                                    VRDE_AUDIO_FMT_BITS_PER_SAMPLE(pParms->fmt),
    1323                                                                                    VRDE_AUDIO_FMT_SIGNED(pParms->fmt)
    1324                                                                                   );
    1325 #else
    13261321            pPort->pfnAudioInputEventBegin (pPort, pvCtx,
    13271322                                            VRDE_AUDIO_FMT_SAMPLE_FREQ(pParms->fmt),
     
    13311326                                           );
    13321327#endif
    1333         } break;
     1328            break;
     1329        }
    13341330
    13351331        case VRDE_AUDIOIN_DATA:
    1336         {
    13371332#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    1338             server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventData(pvCtx, pvData, cbData);
     1333            pServer->mConsole->i_getAudioVRDE()->onVRDEInputData(pvCtx, pvData, cbData);
    13391334#else
    13401335            pPort->pfnAudioInputEventData (pPort, pvCtx, pvData, cbData);
    13411336#endif
    1342         } break;
     1337            break;
    13431338
    13441339        case VRDE_AUDIOIN_END:
    1345         {
    13461340#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    1347             server->mConsole->getAudioVRDE()->handleVRDESvrCmdAudioInputEventEnd(pvCtx);
     1341            pServer->mConsole->i_getAudioVRDE()->onVRDEInputEnd(pvCtx);
    13481342#else
    13491343            pPort->pfnAudioInputEventEnd (pPort, pvCtx);
    13501344#endif
    1351         } break;
     1345            break;
    13521346
    13531347        default:
    1354             return;
    1355     }
    1356 }
    1357 
     1348            break;
     1349    }
     1350}
    13581351
    13591352ConsoleVRDPServer::ConsoleVRDPServer(Console *console)
     
    39063899}
    39073900
    3908 /* @todo rc not needed? */
    39093901int ConsoleVRDPServer::SendAudioInputBegin(void **ppvUserCtx,
    39103902                                           void *pvContext,
     
    39143906                                           uint32_t cBits)
    39153907{
    3916     if (mpEntryPoints && mhServer && mpEntryPoints->VRDEAudioInOpen)
     3908    if (   mhServer
     3909        && mpEntryPoints && mpEntryPoints->VRDEAudioInOpen)
    39173910    {
    39183911        uint32_t u32ClientId = ASMAtomicReadU32(&mu32AudioInputClientId);
     
    39203913        {
    39213914            VRDEAUDIOFORMAT audioFormat = VRDE_AUDIO_FMT_MAKE(iSampleHz, cChannels, cBits, 0);
    3922             mpEntryPoints->VRDEAudioInOpen (mhServer,
    3923                                             pvContext,
    3924                                             u32ClientId,
    3925                                             audioFormat,
    3926                                             cSamples);
    3927 #ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    3928             //*ppvUserCtx = NULL;
    3929 #else
    3930             *ppvUserCtx = NULL; /* This is the ConsoleVRDPServer context.
    3931 -                                * Currently not used because only one client is allowed to
    3932 -                                * do audio input and the client id is saved by the ConsoleVRDPServer.
    3933 -                                */
    3934 #endif
    3935 
     3915            mpEntryPoints->VRDEAudioInOpen(mhServer,
     3916                                           pvContext,
     3917                                           u32ClientId,
     3918                                           audioFormat,
     3919                                           cSamples);
     3920            if (ppvUserCtx)
     3921                *ppvUserCtx = NULL; /* This is the ConsoleVRDPServer context.
     3922                                     * Currently not used because only one client is allowed to
     3923                                     * do audio input and the client ID is saved by the ConsoleVRDPServer.
     3924                                     */
    39363925            return VINF_SUCCESS;
    39373926        }
    39383927    }
     3928
     3929    /*
     3930     * Not supported or no client connected.
     3931     */
    39393932    return VERR_NOT_SUPPORTED;
    39403933}
     
    39513944    }
    39523945}
    3953 
    39543946
    39553947void ConsoleVRDPServer::QueryInfo(uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r51096 r53442  
    11/* $Id$ */
    22/** @file
    3  *
    4  * VBox Audio VRDE backend
     3 * VRDE audio backend for Main.
    54 */
    65
    76/*
    8  * Copyright (C) 2006-2010 Oracle Corporation
     7 * Copyright (C) 2013-2014 Oracle Corporation
    98 *
    109 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2221#include "Logging.h"
    2322
     23#include "../../Devices/Audio/DrvAudio.h"
     24#include "../../Devices/Audio/AudioMixBuffer.h"
     25
     26#include <iprt/mem.h>
     27#include <iprt/cdefs.h>
     28#include <iprt/circbuf.h>
     29
    2430#include <VBox/vmm/pdmaudioifs.h>
    2531#include <VBox/vmm/pdmdrv.h>
     
    2733#include <VBox/vmm/cfgm.h>
    2834#include <VBox/err.h>
    29 #include <iprt/mem.h>
    30 #include <iprt/cdefs.h>
    31 
    32 
    33 /*******************************************************************************
    34  *
    35  * IO Ring Buffer section
    36  *
    37  ******************************************************************************/
    38 
    39 /* Implementation of a lock free ring buffer which could be used in a multi
    40  * threaded environment. Note that only the acquire, release and getter
    41  * functions are threading aware. So don't use reset if the ring buffer is
    42  * still in use. */
    43 typedef struct IORINGBUFFER
    44 {
    45     /* The current read position in the buffer */
    46     uint32_t uReadPos;
    47     /* The current write position in the buffer */
    48     uint32_t uWritePos;
    49     /* How much space of the buffer is currently in use */
    50     volatile uint32_t cBufferUsed;
    51     /* How big is the buffer */
    52     uint32_t cBufSize;
    53     /* The buffer itself */
    54     char *pBuffer;
    55 } IORINGBUFFER;
    56 /* Pointer to an ring buffer structure */
    57 typedef IORINGBUFFER* PIORINGBUFFER;
    58 
    59 PPDMDRVINS gpDrvIns; //@todo handle this bad programming;
    60 
    61 static void IORingBufferCreate(PIORINGBUFFER *ppBuffer, uint32_t cSize)
    62 {
    63     PIORINGBUFFER pTmpBuffer;
    64 
    65     AssertPtr(ppBuffer);
    66 
    67     *ppBuffer = NULL;
    68     pTmpBuffer = RTMemAllocZ(sizeof(IORINGBUFFER));
    69     if (pTmpBuffer)
    70     {
    71         pTmpBuffer->pBuffer = RTMemAlloc(cSize);
    72         if(pTmpBuffer->pBuffer)
    73         {
    74             pTmpBuffer->cBufSize = cSize;
    75             *ppBuffer = pTmpBuffer;
    76         }
    77         else
    78             RTMemFree(pTmpBuffer);
    79     }
    80 }
    81 
    82 static void IORingBufferDestroy(PIORINGBUFFER pBuffer)
    83 {
    84     if (pBuffer)
    85     {
    86         if (pBuffer->pBuffer)
    87             RTMemFree(pBuffer->pBuffer);
    88         RTMemFree(pBuffer);
    89     }
    90 }
    91 
    92 DECL_FORCE_INLINE(void) IORingBufferReset(PIORINGBUFFER pBuffer)
    93 {
    94     AssertPtr(pBuffer);
    95 
    96     pBuffer->uReadPos = 0;
    97     pBuffer->uWritePos = 0;
    98     pBuffer->cBufferUsed = 0;
    99 }
    100 
    101 DECL_FORCE_INLINE(uint32_t) IORingBufferFree(PIORINGBUFFER pBuffer)
    102 {
    103     AssertPtr(pBuffer);
    104     return pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
    105 }
    106 
    107 DECL_FORCE_INLINE(uint32_t) IORingBufferUsed(PIORINGBUFFER pBuffer)
    108 {
    109     AssertPtr(pBuffer);
    110     return ASMAtomicReadU32(&pBuffer->cBufferUsed);
    111 }
    112 
    113 DECL_FORCE_INLINE(uint32_t) IORingBufferSize(PIORINGBUFFER pBuffer)
    114 {
    115     AssertPtr(pBuffer);
    116     return pBuffer->cBufSize;
    117 }
    118 
    119 static void IORingBufferAquireReadBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
    120 {
    121     uint32_t uUsed = 0;
    122     uint32_t uSize = 0;
    123 
    124     AssertPtr(pBuffer);
    125 
    126     *ppStart = 0;
    127     *pcSize = 0;
    128 
    129     /* How much is in use? */
    130     uUsed = ASMAtomicReadU32(&pBuffer->cBufferUsed);
    131     if (uUsed > 0)
    132     {
    133         /* Get the size out of the requested size, the read block till the end
    134          * of the buffer & the currently used size. */
    135         uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uReadPos, uUsed));
    136         if (uSize > 0)
    137         {
    138             /* Return the pointer address which point to the current read
    139              * position. */
    140             *ppStart = pBuffer->pBuffer + pBuffer->uReadPos;
    141             *pcSize = uSize;
    142         }
    143     }
    144 }
    145 
    146 DECL_FORCE_INLINE(void) IORingBufferReleaseReadBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
    147 {
    148     AssertPtr(pBuffer);
    149 
    150     /* Split at the end of the buffer. */
    151     pBuffer->uReadPos = (pBuffer->uReadPos + cSize) % pBuffer->cBufSize;
    152     ASMAtomicSubU32(&pBuffer->cBufferUsed, cSize);
    153 }
    154 
    155 static void IORingBufferAquireWriteBlock(PIORINGBUFFER pBuffer, uint32_t cReqSize, char **ppStart, uint32_t *pcSize)
    156 {
    157     uint32_t uFree;
    158     uint32_t uSize;
    159 
    160     AssertPtr(pBuffer);
    161 
    162     *ppStart = 0;
    163     *pcSize = 0;
    164 
    165     /* How much is free? */
    166     uFree = pBuffer->cBufSize - ASMAtomicReadU32(&pBuffer->cBufferUsed);
    167     if (uFree > 0)
    168     {
    169         /* Get the size out of the requested size, the write block till the end
    170          * of the buffer & the currently free size. */
    171         uSize = RT_MIN(cReqSize, RT_MIN(pBuffer->cBufSize - pBuffer->uWritePos, uFree));
    172         if (uSize > 0)
    173         {
    174             /* Return the pointer address which point to the current write
    175              * position. */
    176             *ppStart = pBuffer->pBuffer + pBuffer->uWritePos;
    177             *pcSize = uSize;
    178         }
    179     }
    180 }
    181 
    182 DECL_FORCE_INLINE(void) IORingBufferReleaseWriteBlock(PIORINGBUFFER pBuffer, uint32_t cSize)
    183 {
    184     AssertPtr(pBuffer);
    185 
    186     /* Split at the end of the buffer. */
    187     pBuffer->uWritePos = (pBuffer->uWritePos + cSize) % pBuffer->cBufSize;
    188 
    189     ASMAtomicAddU32(&pBuffer->cBufferUsed, cSize);
    190 }
    191 
    192 /****************** Ring Buffer Function Ends *****************/
    193 
    194 //@todo need to see if they need to move to pdmifs.h
    195 #define AUDIO_HOST_ENDIANNESS 0
    196 #define VOICE_ENABLE 1
    197 #define VOICE_DISABLE 2
    198 
    199 
    200 /* Initialization status indicator used for the recreation of the AudioUnits. */
    201 #define CA_STATUS_UNINIT    UINT32_C(0) /* The device is uninitialized */
    202 #define CA_STATUS_IN_INIT   UINT32_C(1) /* The device is currently initializing */
    203 #define CA_STATUS_INIT      UINT32_C(2) /* The device is initialized */
    204 #define CA_STATUS_IN_UNINIT UINT32_C(3) /* The device is currently uninitializing */
    205 
    206 //@todo move t_sample as a PDM interface
    207 //typedef struct { int mute;  uint32_t r; uint32_t l; } volume_t;
    208 
    209 #define INT_MAX         0x7fffffff
    210 volume_t nominal_volume = {
    211     0,
    212     INT_MAX,
    213     INT_MAX
    214 };
    215 
    216 /* The desired buffer length in milliseconds. Will be the target total stream
    217  * latency on newer version of pulse. Apparent latency can be less (or more.)
    218  * In case its need to be used. Currently its not used.
    219  */
    220 #if 0
    221 static struct
    222 {
    223     int         buffer_msecs_out;
    224     int         buffer_msecs_in;
    225 } confAudioVRDE
    226 =
    227 {
    228     INIT_FIELD (.buffer_msecs_out = ) 100,
    229     INIT_FIELD (.buffer_msecs_in  = ) 100,
    230 };
     35
     36#ifdef LOG_GROUP
     37 #undef LOG_GROUP
    23138#endif
     39#define LOG_GROUP LOG_GROUP_DEV_AUDIO
     40#include <VBox/log.h>
     41
    23242/**
    23343 * Audio VRDE driver instance data.
    234  *
    235  * @extends PDMIAUDIOSNIFFERCONNECTOR
    23644 */
    23745typedef struct DRVAUDIOVRDE
    23846{
    239     /** Pointer to audio VRDE object */
     47    /** Pointer to audio VRDE object. */
    24048    AudioVRDE           *pAudioVRDE;
    241     PPDMDRVINS          pDrvIns;
     49    PPDMDRVINS           pDrvIns;
    24250    /** Pointer to the driver instance structure. */
    243     PDMIHOSTAUDIO       IHostAudioR3;
    244     ConsoleVRDPServer *pConsoleVRDPServer;
     51    PDMIHOSTAUDIO        IHostAudioR3;
     52    ConsoleVRDPServer   *pConsoleVRDPServer;
    24553    /** Pointer to the DrvAudio port interface that is above it. */
    246     PPDMIAUDIOCONNECTOR       pUpPort;
     54    PPDMIAUDIOCONNECTOR  pDrvAudio;
    24755} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
    248 typedef struct PDMHOSTVOICEOUT PDMHOSTVOICEOUT;
    249 typedef PDMHOSTVOICEOUT *PPDMHOSTVOICEOUT;
    250 
    251 typedef struct VRDEVoice
    252 {
    253     /* Audio and audio details for recording */
    254     PDMHOSTVOICEIN   pHostVoiceIn;
    255     void * pvUserCtx;
    256     /* Number of bytes per frame (bitsPerSample * channels) of the actual input format. */
    257     uint32_t cBytesPerFrame;
    258     /* Frequency of the actual audio format. */
    259     uint32_t uFrequency;
    260     /* If the actual format frequence differs from the requested format, this is not NULL. */
    261     void *rate;
    262     /* Temporary buffer for st_sample_t representation of the input audio data. */
    263     void *pvSamplesBuffer;
    264     /* buffer for bytes of samples (not rate converted) */
    265     uint32_t cbSamplesBufferAllocated;
    266     /* Temporary buffer for frequency conversion. */
    267     void *pvRateBuffer;
    268     /* buffer for bytes rate converted samples */
    269     uint32_t cbRateBufferAllocated;
    270     /* A ring buffer for transferring data to the playback thread */
    271     PIORINGBUFFER pRecordedVoiceBuf;
    272     t_sample * convAudioDevFmtToStSampl;
    273     uint32_t fIsInit;
    274     uint32_t status;
    275 };
    276 typedef VRDEVoice *PVRDEVoice;
    277 
    278 typedef struct VRDEVoiceOut
    279 {
    280     PDMHOSTVOICEOUT pHostVoiceOut;
     56
     57typedef struct VRDESTREAMIN
     58{
     59    /** Associated host input stream. */
     60    PDMAUDIOHSTSTRMIN    HstStrmIn;
     61    /** Number of samples captured asynchronously in the
     62     *  onVRDEInputXXX callbacks. */
     63    uint32_t             cSamplesCaptured;
     64    /** Critical section. */
     65    RTCRITSECT           CritSect;
     66
     67} VRDESTREAMIN, *PVRDESTREAMIN;
     68
     69typedef struct VRDESTREAMOUT
     70{
     71    /** Associated host output stream. */
     72    PDMAUDIOHSTSTRMOUT HstStrmOut;
    28173    uint64_t old_ticks;
    28274    uint64_t cSamplesSentPerSec;
    283 };
    284 typedef VRDEVoiceOut * PVRDEVoiceOut;
    285 
    286 AudioVRDE::AudioVRDE(Console *console)
    287     : mpDrv(NULL),
    288       mParent(console)
    289 {
    290 }
    291 
    292 AudioVRDE::~AudioVRDE()
    293 {
    294     if (mpDrv)
    295     {
    296         mpDrv->pAudioVRDE = NULL;
    297         mpDrv = NULL;
    298     }
    299 }
    300 
    301 PPDMIAUDIOCONNECTOR AudioVRDE::getDrvAudioPort()
    302 {
    303     Assert(mpDrv);
    304     return mpDrv->pUpPort;
    305 }
    306 
    307 void AudioVRDE::handleVRDESvrCmdAudioInputIntercept(bool fIntercept)
    308 {
    309     LogFlow(("AudioVRDE: handleVRDPCmdInputIntercept\n"));
    310 }
    311 
    312 static DECLCALLBACK(void *)  drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
    313 {
    314     LogFlow(("drvAudioVRDEInit \n"));
    315     return 1;
    316 }
    317 
    318 static void drvAudioVRDEPcmInitInfo(PDMPCMPROPERTIES * pProps, audsettings_t *as)
    319 {
    320     int bits = 8, sign = 0, shift = 0;
    321     LogFlow(("AudioVRDE: PcmInitInfo \n"));
    322 
    323     switch (as->fmt) {
    324     case AUD_FMT_S8:
    325         sign = 1;
    326     case AUD_FMT_U8:
    327         break;
    328 
    329     case AUD_FMT_S16:
    330         sign = 1;
    331     case AUD_FMT_U16:
    332         bits = 16;
    333         shift = 1;
    334         break;
    335 
    336     case AUD_FMT_S32:
    337         sign = 1;
    338     case AUD_FMT_U32:
    339         bits = 32;
    340         shift = 2;
    341         break;
    342     }
    343 
    344     pProps->uFrequency = as->freq;
    345     pProps->cBits = bits;
    346     pProps->fSigned = sign;
    347     pProps->cChannels = as->nchannels;
    348     pProps->cShift = (as->nchannels == 2) + shift;
    349     pProps->fAlign = (1 << pProps->cShift) - 1;
    350     pProps->cbPerSec = pProps->uFrequency << pProps->cShift;
    351     pProps->fSwapEndian = (as->endianness != AUDIO_HOST_ENDIANNESS);
    352 }
    353 
    354 /*
    355  * Hard voice (playback)
    356  */
    357 static int audio_pcm_hw_find_min_out (PPDMHOSTVOICEOUT hw, int *nb_livep)
    358 {
    359     PPDMGSTVOICEOUT sw;
    360     PPDMGSTVOICEOUT pIter;
    361     int m = INT_MAX;
    362     int nb_live = 0;
    363     LogFlow(("Hard Voice Playback \n"));
    364 
    365     RTListForEach(&hw->HeadGstVoiceOut, pIter, PDMGSTVOICEOUT, ListGstVoiceOut)
    366     {
    367         sw = pIter;
    368         if (sw->State.fActive || !sw->State.fEmpty)
    369         {
    370             m = audio_MIN (m, sw->cSamplesMixed);
    371             nb_live += 1;
    372         }
    373     }
    374 
    375     *nb_livep = nb_live;
    376     return m;
    377 }
    378 
    379 int audio_pcm_hw_get_live_out2 (PPDMHOSTVOICEOUT hw, int *nb_live)
    380 {
    381     int smin;
    382 
    383     smin = audio_pcm_hw_find_min_out (hw, nb_live);
    384 
    385     if (!*nb_live) {
    386         return 0;
     75} VRDESTREAMOUT, *PVRDESTREAMOUT;
     76
     77static DECLCALLBACK(int) drvAudioVRDEInit(PPDMIHOSTAUDIO pInterface)
     78{
     79    LogFlowFuncEnter();
     80
     81    return VINF_SUCCESS;
     82}
     83
     84static DECLCALLBACK(int) drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface,
     85                                             PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
     86                                             uint32_t *pcSamples)
     87{
     88    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     89    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     90
     91    LogFlowFunc(("pHstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg));
     92
     93    PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
     94    AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
     95
     96    if (pcSamples)
     97        *pcSamples = _4K; /** @todo Make this configurable. */
     98
     99    return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmOut->HstStrmOut.Props);
     100}
     101
     102static DECLCALLBACK(int) drvAudioVRDEInitIn(PPDMIHOSTAUDIO pInterface,
     103                                            PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
     104                                            PDMAUDIORECSOURCE enmRecSource,
     105                                            uint32_t *pcSamples)
     106{
     107    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     108    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     109
     110    PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
     111    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     112
     113    if (pcSamples)
     114        *pcSamples = _4K; /** @todo Make this configurable. */
     115
     116    return drvAudioStreamCfgToProps(pCfg, &pVRDEStrmIn->HstStrmIn.Props);
     117}
     118
     119/**
     120 * Transfers audio input formerly sent by a connected RDP client / VRDE backend
     121 * (using the onVRDEInputXXX methods) over to the VRDE host (VM). The audio device
     122 * emulation then will read and send the data to the guest.
     123 *
     124 * @return  IPRT status code.
     125 * @param   pInterface
     126 * @param   pHstStrmIn
     127 * @param   pcSamplesCaptured
     128 */
     129static DECLCALLBACK(int) drvAudioVRDECaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
     130                                               uint32_t *pcSamplesCaptured)
     131{
     132    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     133    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     134    AssertPtrReturn(pcSamplesCaptured, VERR_INVALID_POINTER);
     135
     136    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     137    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     138
     139    PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
     140    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     141
     142    /** @todo Use CritSect! */
     143
     144    int rc;
     145
     146    uint32_t cProcessed = 0;
     147    if (pVRDEStrmIn->cSamplesCaptured)
     148    {
     149        rc = audioMixBufMixToParent(&pVRDEStrmIn->HstStrmIn.MixBuf, pVRDEStrmIn->cSamplesCaptured,
     150                                    &cProcessed);
    387151    }
    388152    else
    389     {
    390         int live = smin;
    391 
    392         if (live < 0 || live > hw->cSamples)
    393         {
    394             LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
    395             return 0;
    396         }
    397         return live;
    398     }
    399 }
    400 
    401 
    402 int audio_pcm_hw_get_live_out (PPDMHOSTVOICEOUT hw)
    403 {
    404     int nb_live;
    405     int live;
    406 
    407     live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
    408     if (live < 0 || live > hw->cSamples)
    409     {
    410         LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
    411         return 0;
    412     }
    413     return live;
    414 }
    415 
    416 /*
    417  * Hard voice (capture)
    418  */
    419 static int audio_pcm_hw_find_min_in (PPDMHOSTVOICEIN hw)
    420 {
    421     PPDMGSTVOICEIN pIter;
    422     int m = hw->cSamplesCaptured;
    423 
    424     RTListForEach(&hw->HeadGstVoiceIn, pIter, PDMGSTVOICEIN, ListGstVoiceIn)
    425     {
    426         if (pIter->State.fActive)
    427         {
    428             m = audio_MIN (m, pIter->cHostSamplesAcquired);
    429         }
    430     }
    431     return m;
    432 }
    433 
    434 int audio_pcm_hw_get_live_in (PPDMHOSTVOICEIN hw)
    435 {
    436     int live = hw->cSamplesCaptured - audio_pcm_hw_find_min_in (hw);
    437     if (live < 0 || live > hw->cSamples)
    438     {
    439         LogFlow(("Error: live=%d hw->samples=%d\n", live, hw->cSamples));
    440         return 0;
    441     }
    442     return live;
    443 }
    444 
    445 static inline void *advance (void *p, int incr)
    446 {
    447     uint8_t *d = (uint8_t*)p;
    448     return (d + incr);
    449 }
    450 
    451 uint64_t audio_get_ticks_per_sec (void)
    452 {
    453     return PDMDrvHlpTMGetVirtualFreq (gpDrvIns);
    454 }
    455 
    456 uint64_t audio_get_clock (void)
    457 {
    458     return PDMDrvHlpTMGetVirtualTime (gpDrvIns);
    459 }
    460 
    461 void VRDEReallocSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
    462 {
    463     uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
    464     if (cbBuffer > pVRDEVoice->cbSamplesBufferAllocated)
    465     {
    466         if (pVRDEVoice->pvSamplesBuffer)
    467         {
    468             RTMemFree(pVRDEVoice->pvSamplesBuffer);
    469             pVRDEVoice->pvSamplesBuffer = NULL;
    470         }
    471         pVRDEVoice->pvSamplesBuffer = RTMemAlloc(cbBuffer);
    472         if (pVRDEVoice->pvSamplesBuffer)
    473             pVRDEVoice->cbSamplesBufferAllocated = cbBuffer;
    474         else
    475             pVRDEVoice->cbSamplesBufferAllocated = 0;
    476     }
    477 
    478 }
    479 
    480 void VRDEReallocRateAdjSampleBuf(PVRDEVoice pVRDEVoice, uint32_t cSamples)
    481 {
    482     uint32_t cbBuffer = cSamples * sizeof(PDMHOSTSTEREOSAMPLE);
    483     if (cbBuffer > pVRDEVoice->cbRateBufferAllocated)
    484     {
    485         RTMemFree(pVRDEVoice->pvRateBuffer);
    486         pVRDEVoice->pvRateBuffer = RTMemAlloc(cbBuffer);
    487         if (pVRDEVoice->pvRateBuffer)
    488             pVRDEVoice->cbRateBufferAllocated = cbBuffer;
    489         else
    490             pVRDEVoice->cbRateBufferAllocated = 0;
    491     }
    492 }
    493 
    494 /*******************************************************************************
     153        rc = VINF_SUCCESS;
     154
     155    if (RT_SUCCESS(rc))
     156    {
     157        *pcSamplesCaptured = cProcessed;
     158
     159        Assert(pVRDEStrmIn->cSamplesCaptured >= cProcessed);
     160        pVRDEStrmIn->cSamplesCaptured -= cProcessed;
     161    }
     162
     163    LogFlowFunc(("cSamplesCaptured=%RU32, cProcessed=%RU32\n",
     164                 pVRDEStrmIn->cSamplesCaptured, cProcessed, rc));
     165    return rc;
     166}
     167
     168/**
     169 * Transfers VM audio output over to the VRDE instance for playing remotely
     170 * on the client.
    495171 *
    496  * AudioVRDE input section
    497  *
    498  ******************************************************************************/
    499 
    500 /*
    501  * Callback to feed audio input buffer. Samples format is be the same as
    502  * in the voice. The caller prepares st_sample_t.
    503  *
    504  * @param cbSamples Size of pvSamples array in bytes.
    505  * @param pvSamples Points to an array of samples.
    506  *
    507  * @return IPRT status code.
    508  */
    509 static int fltRecordingCallback(PVRDEVoice pVRDEVoice, uint32_t cbSamples, const void *pvSamples)
    510 {
    511     int rc = VINF_SUCCESS;
    512     uint32_t csAvail = 0;
    513     uint32_t csToWrite = 0;
    514     uint32_t cbToWrite = 0;
    515     uint32_t csWritten = 0;
    516     char *pcDst = NULL;
    517 
    518     LogFlow(("audio-filter: fltRecordingCallback\n"));
    519 
    520     Assert((cbSamples % sizeof(PDMHOSTSTEREOSAMPLE)) == 0);
    521 
    522     if (!pVRDEVoice->fIsInit)
    523         return VINF_SUCCESS;
    524 
    525     /* If nothing is pending return immediately. */
    526     if (cbSamples == 0)
    527         return VINF_SUCCESS;
    528 
    529     /* How much space is free in the ring buffer? */
    530     PPDMHOSTSTEREOSAMPLE psSrc;
    531     csAvail = IORingBufferFree(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE); /* bytes -> samples */
    532 
    533     /* How much space is used in the audio buffer. Use the smaller size of the too. */
    534     csAvail = RT_MIN(csAvail, cbSamples / sizeof(PDMHOSTSTEREOSAMPLE));
    535 
    536     /* Iterate as long as data is available */
    537     while(csWritten < csAvail)
    538     {
    539         /* How much is left? */
    540         csToWrite = csAvail - csWritten;
    541         cbToWrite = csToWrite * sizeof(PDMHOSTSTEREOSAMPLE);
    542 
    543         /* Try to acquire the necessary space from the ring buffer. */
    544         IORingBufferAquireWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite, &pcDst, &cbToWrite);
    545 
    546         /* How much do we get? */
    547         csToWrite = cbToWrite / sizeof(PDMHOSTSTEREOSAMPLE);
    548 
    549             /* Break if nothing is free anymore. */
    550         if (RT_UNLIKELY(csToWrite == 0))
    551             break;
    552 
    553         /* Copy the data from the audio buffer to the ring buffer in PVRDEVoice. */
    554         memcpy(pcDst, (uint8_t *)pvSamples + (csWritten * sizeof(PDMHOSTSTEREOSAMPLE)), cbToWrite);
    555 
    556         /* Release the ring buffer, so the main thread could start reading this data. */
    557         IORingBufferReleaseWriteBlock(pVRDEVoice->pRecordedVoiceBuf, cbToWrite);
    558 
    559         csWritten += csToWrite;
    560     }
    561 
    562     LogFlow(("AudioVRDE: [Input] Finished writing buffer with %RU32 samples (%RU32 bytes)\n",
    563               csWritten, csWritten * sizeof(PDMHOSTSTEREOSAMPLE)));
    564 
    565     return rc;
    566 }
    567 
    568 
    569 STDMETHODIMP AudioVRDE::handleVRDESvrCmdAudioInputEventBegin(void *pvContext, int iSampleHz, int cChannels,
    570                                                              int cBits, bool fUnsigned)
    571 {
    572     int bitIdx;
    573     PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
    574     LogFlow(("AudioVRDE: handleVRDPCmdInputEventBegin\n"));
    575     /* Prepare a format convertion for the actually used format. */
    576     pVRDEVoice->cBytesPerFrame = ((cBits + 7) / 8) * cChannels;
    577     if (cBits == 16)
    578     {
    579         bitIdx = 1;
    580     }
    581     else if (cBits == 32)
    582     {
    583         bitIdx = 2;
    584     }
    585     else
    586     {
    587         bitIdx = 0;
    588     }
    589     //PPDMIAUDIOCONNECTOR pPort = server->mConsole->getAudioVRDE()->getDrvAudioPort();
    590     /* Call DrvAudio interface to get the t_sample type conversion function */
    591     pVRDEVoice->convAudioDevFmtToStSampl = mpDrv->pUpPort->pfnConvDevFmtToStSample(mpDrv->pUpPort,
    592                                                                                    (cChannels == 2) ? 1 : 0,
    593                                                                                    !fUnsigned, 0, bitIdx
    594                                                                                   );
    595     if (pVRDEVoice->convAudioDevFmtToStSampl)
    596     {
    597         LogFlow(("AudioVRDE: Failed to get the conversion function \n"));
    598     }
    599     LogFlow(("AudioVRDE: Required freq as requested by VRDP Server = %d\n", iSampleHz));
    600     //if (iSampleHz && iSampleHz != pVRDEVoice->pHostVoiceIn.Props.uFrequency)
    601     {
    602         /* @todo if the above condition is false then pVRDEVoice->uFrequency will remain 0 */
    603         pVRDEVoice->rate = mpDrv->pUpPort->pfnPrepareAudioConversion(mpDrv->pUpPort, iSampleHz,
    604                                                                      pVRDEVoice->pHostVoiceIn.Props.uFrequency);
    605         pVRDEVoice->uFrequency = iSampleHz;
    606         LogFlow(("AudioVRDE: pVRDEVoice assigned requested freq =%d\n", pVRDEVoice->uFrequency));
    607     }
    608     return VINF_SUCCESS;
    609 }
    610 
    611 /*
    612  * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
    613  *            drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
    614  */
    615 void AudioVRDE::handleVRDESvrCmdAudioInputEventData(void *pvContext, const void *pvData, uint32_t cbData)
    616 {
    617     PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
    618     PPDMHOSTSTEREOSAMPLE pHostStereoSampleBuf; /* target sample buffer */
    619     PPDMHOSTSTEREOSAMPLE pConvertedSampleBuf; /* samples adjusted for rate */
    620     uint32_t cSamples = cbData / pVRDEVoice->cBytesPerFrame; /* Count of samples */
    621     void * pTmpSampleBuf = NULL;
    622     uint32_t cConvertedSamples; /* samples adjusted for rate */
    623     uint32_t cbSamples; /* count of bytes occupied by samples */
    624     uint32_t rc;
    625     LogFlow(("AudioVRDE: handleVRDPCmdInputEventData cbData = %d, bytesperfram=%d\n",
    626               cbData, pVRDEVoice->cBytesPerFrame));
    627 
    628     VRDEReallocSampleBuf(pVRDEVoice, cSamples);
    629     pHostStereoSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvSamplesBuffer;
    630     pVRDEVoice->convAudioDevFmtToStSampl(pHostStereoSampleBuf, pvData, cSamples, &nominal_volume);
    631 
    632     /* count of rate adjusted samples */
    633     pVRDEVoice->uFrequency = 22100; /* @todo handle this. How pVRDEVoice will get proper value */
    634     cConvertedSamples = (cSamples * pVRDEVoice->pHostVoiceIn.Props.uFrequency) / pVRDEVoice->uFrequency;
    635     VRDEReallocRateAdjSampleBuf(pVRDEVoice, cConvertedSamples);
    636 
    637     pConvertedSampleBuf = (PPDMHOSTSTEREOSAMPLE)pVRDEVoice->pvRateBuffer;
    638 
    639     if (pConvertedSampleBuf)
    640     {
    641         uint32_t cSampleSrc = cSamples;
    642         uint32_t cSampleDst = cConvertedSamples;
    643         mpDrv->pUpPort->pfnDoRateConversion(mpDrv->pUpPort, pVRDEVoice->rate, pHostStereoSampleBuf,
    644                                             pConvertedSampleBuf, &cSampleSrc, &cConvertedSamples);
    645         pTmpSampleBuf = pConvertedSampleBuf;
    646         cbSamples =  cConvertedSamples * sizeof(PDMHOSTSTEREOSAMPLE);
    647     }
    648 
    649     if (cbSamples)
    650     {
    651         rc = fltRecordingCallback(pVRDEVoice, cbSamples, pTmpSampleBuf);
    652     }
    653 }
    654 
    655 /*
    656  * pvContext: pointer to VRDP voice returned by the VRDP server. The is same pointer that we initialized in
    657  *            drvAudioVRDEDisableEnableIn VOICE_ENABLE case.
    658  */
    659 void AudioVRDE::handleVRDESvrCmdAudioInputEventEnd(void *pvContext)
    660 {
    661     PVRDEVoice pVRDEVoice = (PVRDEVoice)pvContext;
    662     LogFlow(("AudioVRDE: handleVRDPCmdInputEventEnd\n"));
    663      /* The caller will not use this context anymore. */
    664     if (pVRDEVoice->rate)
    665     {
    666         mpDrv->pUpPort->pfnEndAudioConversion(mpDrv->pUpPort, pVRDEVoice->rate);
    667     }
    668 
    669     if (pVRDEVoice->pvSamplesBuffer)
    670     {
    671         RTMemFree(pVRDEVoice->pvSamplesBuffer);
    672         pVRDEVoice->pvSamplesBuffer = NULL;
    673     }
    674     if(pVRDEVoice->pvRateBuffer)
    675     {
    676         RTMemFree(pVRDEVoice->pvRateBuffer);
    677         pVRDEVoice->pvRateBuffer = NULL;
    678     }
    679 }
    680 
    681 static DECLCALLBACK(int)  drvAudioVRDEInitOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut, audsettings_t *as)
    682 {
    683     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    684 
    685     PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
    686     LogFlow(("DrvAudioVRDEInitOut: audio input begin cShift=%d\n", pHostVoiceOut->Props.cShift));
    687     pHostVoiceOut->cSamples =  6174;
    688     drvAudioVRDEPcmInitInfo(&pVRDEVoiceOut->pHostVoiceOut.Props, as);
    689     return VINF_SUCCESS;
    690 
    691 }
    692 
    693 static DECLCALLBACK(int) drvAudioVRDEInitIn (PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, audsettings_t *as)
    694 {
    695     LogFlow(("DrvAudioVRDE: drvAudioVRDEInitIn \n"));
    696     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    697     PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
    698     pHostVoiceIn->cSamples =  6174;
    699     drvAudioVRDEPcmInitInfo(&pVRDEVoice->pHostVoiceIn.Props, as);
    700     return VINF_SUCCESS;
    701 }
    702 
    703 static DECLCALLBACK(int) drvAudioVRDEPlayIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn)
    704 {
    705     uint32_t cbAvlblRingBuffer = 0;
    706     uint32_t cSamplesRingBuffer = 0;
    707     uint32_t cSamplesToRead = 0;
    708     uint32_t cSamplesRead = 0;
    709     uint32_t cbToRead;
    710     char *pcSrc;
    711     PDMHOSTSTEREOSAMPLE * psDst;
    712     //@todo take care of the size of the buffer allocated to pHostVoiceIn
    713     PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
    714     LogFlow(("DrvAudioVRDE: drvAudioVRDEPlayIn \n"));
    715 
    716  /* use this from DrvHostCoreAudio.c */
    717     if (ASMAtomicReadU32(&pVRDEVoice->status) != CA_STATUS_INIT)
    718     {
    719         LogFlow(("AudioVRDE: VRDE voice not initialized \n"));
    720         return 0;
    721     }
    722 
    723     /* how much space is used in the ring buffer in pRecordedVocieBuf with pAudioVRDE . Bytes-> samples*/
    724     cSamplesRingBuffer = IORingBufferUsed(pVRDEVoice->pRecordedVoiceBuf) / sizeof(PDMHOSTSTEREOSAMPLE);
    725 
    726     /* How much space is available in the mix buffer. Use the smaller size of the too. */
    727     cSamplesRingBuffer = RT_MIN(cSamplesRingBuffer, (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples -
    728                                audio_pcm_hw_get_live_in (&pVRDEVoice->pHostVoiceIn)));
    729     LogFlow(("AudioVRDE: [Input] Start reading buffer with %d samples (%d bytes)\n", cSamplesRingBuffer,
    730               cSamplesRingBuffer * sizeof(PDMHOSTSTEREOSAMPLE)));
    731 
    732     /* Iterate as long as data is available */
    733     while (cSamplesRead < cSamplesRingBuffer)
    734     {
    735         /* How much is left? Split request at the end of our samples buffer. */
    736         cSamplesToRead = RT_MIN(cSamplesRingBuffer - cSamplesRead,
    737                                 (uint32_t)(pVRDEVoice->pHostVoiceIn.cSamples - pVRDEVoice->pHostVoiceIn.offWrite));
    738         cbToRead = cSamplesToRead * sizeof(PDMHOSTSTEREOSAMPLE);
    739         LogFlow(("AudioVRDE: [Input] Try reading %RU32 samples (%RU32 bytes)\n", cSamplesToRead, cbToRead));
    740 
    741         /* Try to acquire the necessary block from the ring buffer. Remeber in fltRecrodCallback we
    742          * we are filling this buffer with the audio data available from VRDP. Here we are reading it
    743          */
    744         /*todo do I need to introduce a thread to fill the buffer in fltRecordcallback. So that
    745          * filling is in separate thread and the reading of that buffer is in separate thread
    746          */
    747         IORingBufferAquireReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead, &pcSrc, &cbToRead);
    748 
    749         /* How much to we get? */
    750         cSamplesToRead = cbToRead / sizeof(PDMHOSTSTEREOSAMPLE);
    751         LogFlow(("AuderVRDE: [Input] There are %d samples (%d bytes) available\n", cSamplesToRead, cbToRead));
    752 
    753         /* Break if nothing is used anymore. */
    754         if (cSamplesToRead == 0)
    755         {
    756             LogFlow(("AudioVRDE: Nothing to read \n"));
    757             break;
    758         }
    759 
    760         /* Copy the data from our ring buffer to the mix buffer. */
    761         psDst = pVRDEVoice->pHostVoiceIn.pConversionBuf + pVRDEVoice->pHostVoiceIn.offWrite;
    762         memcpy(psDst, pcSrc, cbToRead);
    763 
    764         /* Release the read buffer, so it could be used for new data. */
    765         IORingBufferReleaseReadBlock(pVRDEVoice->pRecordedVoiceBuf, cbToRead);
    766 
    767         pVRDEVoice->pHostVoiceIn.offWrite = (pVRDEVoice->pHostVoiceIn.offWrite + cSamplesToRead)
    768                                               % pVRDEVoice->pHostVoiceIn.cSamples;
    769 
    770         /* How much have we reads so far. */
    771         cSamplesRead += cSamplesToRead;
    772     }
    773     LogFlow(("AudioVRDE: [Input] Finished reading buffer with %d samples (%d bytes)\n",
    774                cSamplesRead, cSamplesRead * sizeof(PDMHOSTSTEREOSAMPLE)));
    775 
    776     return cSamplesRead;
    777 }
    778 
    779 static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
    780 {
    781     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    782     PVRDEVoiceOut pVRDEVoiceOut = (PVRDEVoiceOut)pHostVoiceOut;
    783     int live;
    784     uint8_t     *pu8Dst;
    785     int cSamplesPlayed;
    786     int cSamplesToSend = 0;
     172 * @return  IPRT status code.
     173 * @param   pInterface
     174 * @param   pHstStrmOut
     175 * @param   pcSamplesPlayed
     176 */
     177static DECLCALLBACK(int) drvAudioVRDEPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
     178                                             uint32_t *pcSamplesPlayed)
     179{
     180    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     181    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     182    /* pcSamplesPlayed is optional. */
     183
     184    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     185    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     186    PVRDESTREAMOUT pVRDEStrmOut = (PVRDESTREAMOUT)pHstStrmOut;
     187    AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
     188
    787189    /*
    788190     * Just call the VRDP server with the data.
    789191     */
    790     live = audio_pcm_hw_get_live_out (pHostVoiceOut);
    791     uint64_t now = audio_get_clock();
    792     uint64_t ticks = now  - pVRDEVoiceOut->old_ticks;
    793     uint64_t ticks_per_second = audio_get_ticks_per_sec();
    794     cSamplesPlayed = (int)((2 * ticks * pHostVoiceOut->Props.uFrequency + ticks_per_second) / ticks_per_second / 2);
    795     if (cSamplesPlayed < 0)
     192    uint32_t live = drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */);
     193    uint64_t now = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
     194    uint64_t ticks = now  - pVRDEStrmOut->old_ticks;
     195    uint64_t ticks_per_second = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
     196
     197    uint32_t cSamplesPlayed = (int)((2 * ticks * pHstStrmOut->Props.uHz + ticks_per_second) / ticks_per_second / 2);
     198    if (!cSamplesPlayed)
    796199        cSamplesPlayed = live;
    797     pHostVoiceOut->Props.cBits = 128;
    798     VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHostVoiceOut->Props.uFrequency,
    799                                                  pHostVoiceOut->Props.cChannels,
    800                                                  pHostVoiceOut->Props.cBits, /* bits per sample */
    801                                                  !pHostVoiceOut->Props.fSigned);
    802     LogFlow(("DrvAudioVRDE: send audio sample freq=%d, chan=%d, cBits = %d, fsigned = %d, cSamples=%d format=%d \n",
    803              pHostVoiceOut->Props.uFrequency, pHostVoiceOut->Props.cChannels,
    804              pHostVoiceOut->Props.cBits, pHostVoiceOut->Props.fSigned,
    805              pHostVoiceOut->cSamples, format)
    806             );
    807     pVRDEVoiceOut->old_ticks = now;
    808     cSamplesToSend = RT_MIN(live, cSamplesPlayed);
    809     if (pHostVoiceOut->offRead + cSamplesToSend > pHostVoiceOut->cSamples)
    810     {
    811         /* send the samples till the end of pHostStereoSampleBuf */
    812         pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
    813                                                    (pHostVoiceOut->cSamples - pHostVoiceOut->offRead), format);
    814         /*pHostStereoSampleBuff already has the samples which exceeded its space. They have overwriten the old
    815          * played sampled starting from offset 0. So based on the number of samples that we had to play,
    816          * read the number of samples from offset 0 .
    817          */
    818         pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[0],
    819                                                    (cSamplesToSend - (pHostVoiceOut->cSamples -
    820                                                                      pHostVoiceOut->offRead)),
    821                                                    format);
    822     }
    823     else
    824     {
    825         pDrv->pConsoleVRDPServer->SendAudioSamples(&pHostVoiceOut->pHostSterioSampleBuf[pHostVoiceOut->offRead],
    826                                                    cSamplesToSend, format);
    827     }
    828         pHostVoiceOut->offRead = (pHostVoiceOut->offRead + cSamplesToSend) % pHostVoiceOut->cSamples;
    829     return  cSamplesToSend;
    830 }
    831 
    832 static DECLCALLBACK(void) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN hw)
    833 {
    834     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    835     LogFlow(("DrvAudioVRDE: drvAudioVRDEFiniIn \n"));
    836     pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
    837 }
    838 
    839 static DECLCALLBACK(void) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT pHostVoiceOut)
    840 {
    841     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    842     LogFlow(("DrvAudioVRDE: audio input end\n"));
    843 }
    844 
    845 static DECLCALLBACK(int) drvAudioVRDEDisableEnableOut(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEOUT hw, int cmd)
    846 {
    847     LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableOut \n"));
    848     return VINF_SUCCESS;
    849 }
    850 
    851 static DECLCALLBACK(int) drvAudioVRDEDisableEnableIn(PPDMIHOSTAUDIO pInterface, PPDMHOSTVOICEIN pHostVoiceIn, int cmd)
    852 {
    853     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
    854 
    855     /* Initialize  VRDEVoice and return to VRDP server which returns this struct back to us
    856      * in the form void * pvContext
    857      */
    858     PVRDEVoice pVRDEVoice = (PVRDEVoice)pHostVoiceIn;
    859     LogFlow(("DrvAudioVRDE: drvAudioVRDEDisableEnableIn \n"));
    860     /* initialize only if not already done */
    861     if (cmd == VOICE_ENABLE)
    862     {
    863         //@todo if (!pVRDEVoice->fIsInit)
    864         //    IORingBufferReset(pVRDEVoice->pRecordedVoiceBuf);
    865         LogFlow(("DrvAudioVRDE: Intializing the VRDE params and buffer \n"));
    866         pVRDEVoice->fIsInit = 1;
    867         pVRDEVoice->pHostVoiceIn = *pHostVoiceIn;
    868         pVRDEVoice->cBytesPerFrame =1 ;
    869         pVRDEVoice->uFrequency = 0;
    870         pVRDEVoice->rate = NULL;
    871         pVRDEVoice->cbSamplesBufferAllocated = 0;
    872         pVRDEVoice->pvRateBuffer = NULL;
    873         pVRDEVoice->cbRateBufferAllocated = 0;
    874 
    875         pVRDEVoice->pHostVoiceIn.cSamples = 2048;
    876         /* Initialize the hardware info section with the audio settings */
    877 
    878         ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_INIT);
    879 
    880         /* Create the internal ring buffer. */
    881         IORingBufferCreate(&pVRDEVoice->pRecordedVoiceBuf,
    882                            pVRDEVoice->pHostVoiceIn.cSamples * sizeof(PDMHOSTSTEREOSAMPLE));
    883 
    884         if (!RT_VALID_PTR(pVRDEVoice->pRecordedVoiceBuf))
     200
     201    VRDEAUDIOFORMAT format = VRDE_AUDIO_FMT_MAKE(pHstStrmOut->Props.uHz,
     202                                                 pHstStrmOut->Props.cChannels,
     203                                                 pHstStrmOut->Props.cBits,
     204                                                 pHstStrmOut->Props.fSigned);
     205
     206    LogFlowFunc(("hz=%d, chan=%d, cBits=%d, fSigned=%RTbool, format=%ld\n",
     207                 pHstStrmOut->Props.uHz, pHstStrmOut->Props.cChannels,
     208                 pHstStrmOut->Props.cBits, pHstStrmOut->Props.fSigned,
     209                 format));
     210
     211    pVRDEStrmOut->old_ticks = now;
     212    int cSamplesToSend = RT_MIN(live, cSamplesPlayed);
     213
     214    uint32_t cReadTotal = 0;
     215
     216    PPDMAUDIOSAMPLE pSamples;
     217    uint32_t cRead;
     218    int rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend,
     219                                &pSamples, &cRead);
     220    if (RT_SUCCESS(rc))
     221    {
     222        cReadTotal = cRead;
     223        pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
     224
     225        if (rc == VINF_TRY_AGAIN)
    885226        {
    886             LogRel(("AudioVRDE: [Input] Failed to create internal ring buffer\n"));
    887             return  VERR_NO_MEMORY;
     227            rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead,
     228                                    &pSamples, &cRead);
     229            if (RT_SUCCESS(rc))
     230            {
     231                cReadTotal += cRead;
     232                pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
     233            }
    888234        }
    889 
    890         ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_INIT);
    891         return pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEVoice, pHostVoiceIn->cSamples,
    892                                                              pHostVoiceIn->Props.uFrequency,
    893                                                              pHostVoiceIn->Props.cChannels, pHostVoiceIn->Props.cBits);
    894     }
    895     else if (cmd == VOICE_DISABLE)
    896     {
    897         LogFlow(("DrvAudioVRDE: Cmd to disable VRDE \n"));
    898         pVRDEVoice->fIsInit = 0;
    899         ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_IN_UNINIT);
    900         IORingBufferDestroy(pVRDEVoice->pRecordedVoiceBuf);
    901         pVRDEVoice->pRecordedVoiceBuf = NULL;
    902         ASMAtomicWriteU32(&pVRDEVoice->status, CA_STATUS_UNINIT);
     235    }
     236
     237    audioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     238
     239    if (pcSamplesPlayed)
     240        *pcSamplesPlayed = cReadTotal;
     241
     242    LogFlowFunc(("cSamplesToSend=%RU32, rc=%Rrc\n", cSamplesToSend, rc));
     243    return rc;
     244}
     245
     246static DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     247{
     248    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     249    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     250
     251    if (pDrv->pConsoleVRDPServer)
    903252        pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
    904     }
    905     return VINF_SUCCESS;
    906 }
    907 
    908 static DECLCALLBACK(void) drvAudioVRDEGetConf(PPDMIBASE pInterface, PPDMAUDIOCONF pAudioConf)
    909 {
    910     LogFlow(("drvAudioVRDE: drvAudioVRDEGetConf \n"));
    911     /* @todo check if szHostVoiceOut = sizeof VRDEVoice works. VRDEVoice doesn't contain HOSTVOICEOUT. */
    912     pAudioConf->szHostVoiceOut = sizeof(VRDEVoice);
    913     pAudioConf->szHostVoiceIn = sizeof(VRDEVoice);
    914     pAudioConf->MaxHostVoicesOut = 1;
    915     pAudioConf->MaxHostVoicesIn = 1;
     253
     254    return VINF_SUCCESS;
     255}
     256
     257static DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     258{
     259    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     260    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     261
     262    return VINF_SUCCESS;
     263}
     264
     265static DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
     266                                                PDMAUDIOSTREAMCMD enmStreamCmd)
     267{
     268    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     269    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     270
     271    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     272
     273    return VINF_SUCCESS;
     274}
     275
     276static DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn2, /** @todo Fix param types! */
     277                                               PDMAUDIOSTREAMCMD enmStreamCmd)
     278{
     279    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
     280    AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
     281
     282    PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn2;
     283    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     284
     285    PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn;
     286
     287    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     288
     289    /* Initialize only if not already done. */
     290    if (enmStreamCmd == PDMAUDIOSTREAMCMD_ENABLE)
     291    {
     292        int rc2 = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pHstStrmIn->MixBuf),
     293                                                                pHstStrmIn->Props.uHz,
     294                                                                pHstStrmIn->Props.cChannels, pHstStrmIn->Props.cBits);
     295#ifdef DEBUG
     296        if (rc2 == VERR_NOT_SUPPORTED)
     297            LogFlowFunc(("No RDP client connected, so no input recording supported\n"));
     298#endif
     299    }
     300    else if (enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE)
     301        pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
     302
     303    return VINF_SUCCESS;
     304}
     305
     306static DECLCALLBACK(int) drvAudioVRDEGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     307{
     308    pCfg->cbStreamOut     = sizeof(VRDESTREAMOUT);
     309    pCfg->cbStreamIn      = sizeof(VRDESTREAMIN);
     310    pCfg->cMaxHstStrmsOut = 1;
     311    pCfg->cMaxHstStrmsIn  = 2; /* Microphone in + line in. */
     312
     313    return VINF_SUCCESS;
    916314}
    917315
     
    922320{
    923321    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    924     PDRVAUDIOVRDE  pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
     322    PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
     323
    925324    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    926325    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudioR3);
     
    928327}
    929328
    930 
    931 static DECLCALLBACK(void) drvAudioVRDEDestruct(PPDMDRVINS pDrvIns)
    932 {
    933 }
    934 
    935 /**
    936  * Construct a DirectSound Audio driver instance.
     329AudioVRDE::AudioVRDE(Console *pConsole)
     330    : mpDrv(NULL),
     331      mParent(pConsole)
     332{
     333}
     334
     335AudioVRDE::~AudioVRDE(void)
     336{
     337    if (mpDrv)
     338    {
     339        mpDrv->pAudioVRDE = NULL;
     340        mpDrv = NULL;
     341    }
     342}
     343
     344int AudioVRDE::onVRDEInputIntercept(bool fIntercept)
     345{
     346    LogFlowThisFunc(("fIntercept=%RTbool\n", fIntercept));
     347    return VINF_SUCCESS; /* Never veto. */
     348}
     349
     350/**
     351 * Marks the beginning of sending captured audio data from a connected
     352 * RDP client.
     353 *
     354 * @return  IPRT status code.
     355 * @param   pvContext               The context; in this case a pointer to a
     356 *                                  VRDESTREAMIN structure.
     357 * @param   pVRDEAudioBegin         Pointer to a VRDEAUDIOINBEGIN structure.
     358 */
     359int AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
     360{
     361    AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
     362    AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
     363
     364    PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
     365    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     366
     367    VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
     368
     369    int iSampleHz  = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);
     370    int cChannels  = VRDE_AUDIO_FMT_CHANNELS(audioFmt);
     371    int cBits      = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt);
     372    bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);
     373
     374    /*pVRDEStrmIn->cbSample = VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt);
     375    pVRDEStrmIn->uHz      = iSampleHz;*/
     376
     377    LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
     378                 VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), iSampleHz, cChannels, cBits, fUnsigned));
     379
     380    return VINF_SUCCESS;
     381}
     382
     383int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
     384{
     385    PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
     386    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     387
     388    PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn;
     389    AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     390
     391    /** @todo Use CritSect! */
     392
     393    uint32_t cWritten;
     394    int rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pvData, cbData, &cWritten);
     395    if (RT_SUCCESS(rc))
     396        pVRDEStrmIn->cSamplesCaptured += cWritten;
     397
     398    LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n",
     399                 cbData, cWritten, pVRDEStrmIn->cSamplesCaptured, rc));
     400    return rc;
     401}
     402
     403int AudioVRDE::onVRDEInputEnd(void *pvContext)
     404{
     405    NOREF(pvContext);
     406
     407    return VINF_SUCCESS;
     408}
     409
     410/**
     411 * Construct a VRDE audio driver instance.
    937412 *
    938413 * @copydoc FNPDMDRVCONSTRUCT
    939414 */
    940 DECLCALLBACK(int) AudioVRDE::drvAudioVRDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
     415/* static */
     416DECLCALLBACK(int) AudioVRDE::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
    941417{
    942418    PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
    943     LogRel(("drvAudioVRDEConstruct\n"));
    944 
    945     /* we save the address of AudioVRDE in Object node in CFGM tree and address of VRDP server in
    946      * ObjectVRDPServer node. So presence of both is necessary.
    947      */
    948     //if (!CFGMR3AreValuesValid(pCfg, "Object\0") || !CFGMR3AreValuesValid(pCfg, "ObjectVRDPServer\0"))
    949     //   return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
     419    LogRel(("Audio: Initializing VRDE driver\n"));
     420    LogFlowFunc(("fFlags=0x%x\n", fFlags));
     421
    950422    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
    951423                    ("Configuration error: Not possible to attach anything to this driver!\n"),
     
    955427     * Init the static parts.
    956428     */
    957     pThis->pDrvIns                          = pDrvIns;
    958     gpDrvIns = pDrvIns;
     429    pThis->pDrvIns                    = pDrvIns;
    959430    /* IBase */
    960     pDrvIns->IBase.pfnQueryInterface        = drvAudioVRDEQueryInterface;
    961     pThis->IHostAudioR3.pfnInitIn           = drvAudioVRDEInitIn;
    962     pThis->IHostAudioR3.pfnInitOut          = drvAudioVRDEInitOut;
    963     pThis->IHostAudioR3.pfnDisableEnableOut = drvAudioVRDEDisableEnableOut;
    964     pThis->IHostAudioR3.pfnDisableEnableIn  = drvAudioVRDEDisableEnableIn;
    965     pThis->IHostAudioR3.pfnFiniIn           = drvAudioVRDEFiniIn;
    966     pThis->IHostAudioR3.pfnFiniOut          = drvAudioVRDEFiniOut;
    967     pThis->IHostAudioR3.pfnPlayIn           = drvAudioVRDEPlayIn;
    968     pThis->IHostAudioR3.pfnPlayOut          = drvAudioVRDEPlayOut;
    969     pThis->IHostAudioR3.pfnGetConf          = drvAudioVRDEGetConf;
    970     pThis->IHostAudioR3.pfnInit             = drvAudioVRDEInit;
    971 
    972     /* Get VRDPServer pointer */
    973     void *pv;
    974     int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pv);
     431    pDrvIns->IBase.pfnQueryInterface  = drvAudioVRDEQueryInterface;
     432    pThis->IHostAudioR3.pfnInitIn     = drvAudioVRDEInitIn;
     433    pThis->IHostAudioR3.pfnInitOut    = drvAudioVRDEInitOut;
     434    pThis->IHostAudioR3.pfnControlOut = drvAudioVRDEControlOut;
     435    pThis->IHostAudioR3.pfnControlIn  = drvAudioVRDEControlIn;
     436    pThis->IHostAudioR3.pfnFiniIn     = drvAudioVRDEFiniIn;
     437    pThis->IHostAudioR3.pfnFiniOut    = drvAudioVRDEFiniOut;
     438    pThis->IHostAudioR3.pfnCaptureIn  = drvAudioVRDECaptureIn;
     439    pThis->IHostAudioR3.pfnPlayOut    = drvAudioVRDEPlayOut;
     440    pThis->IHostAudioR3.pfnGetConf    = drvAudioVRDEGetConf;
     441    pThis->IHostAudioR3.pfnInit       = drvAudioVRDEInit;
     442
     443    /* Get VRDPServer pointer. */
     444    void *pvUser;
     445    int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pvUser);
    975446    if (RT_FAILURE(rc))
    976447    {
    977         AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
     448        AssertMsgFailed(("Confguration error: No/bad \"ObjectVRDPServer\" value, rc=%Rrc\n", rc));
    978449        return rc;
    979450    }
    980     /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE */
    981     pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pv;
    982     pv = NULL;
    983 
    984     rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
     451
     452    /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
     453    pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser;
     454
     455    pvUser = NULL;
     456    rc = CFGMR3QueryPtr(pCfg, "Object", &pvUser);
    985457    if (RT_FAILURE(rc))
    986458    {
    987         AssertMsgFailed(("DrvAudioVRDE Confguration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
     459        AssertMsgFailed(("Confguration error: No/bad \"Object\" value, rc=%Rrc\n", rc));
    988460        return rc;
    989461    }
    990     pThis->pAudioVRDE = (AudioVRDE *)pv;
     462
     463    pThis->pAudioVRDE = (AudioVRDE *)pvUser;
    991464    pThis->pAudioVRDE->mpDrv = pThis;
     465
    992466    /*
    993      * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls .
     467     * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls.
    994468     * Described in CFGM tree.
    995469     */
    996     pThis->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
    997     if (!pThis->pUpPort)
    998     {
    999         AssertMsgFailed(("Configuration error: No Audio Sniffer port interface above!\n"));
     470    pThis->pDrvAudio = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
     471    if (!pThis->pDrvAudio)
     472    {
     473        AssertMsgFailed(("Configuration error: No upper interface specified!\n"));
    1000474        return VERR_PDM_MISSING_INTERFACE_ABOVE;
    1001475    }
     
    1004478}
    1005479
    1006 
    1007 /**
    1008  * Char driver registration record.
    1009  */
    1010 const PDMDRVREG g_DrvAudioVRDE =
    1011 {
    1012      PDM_DRVREG_VERSION,
    1013    /* szName */
     480/* static */
     481DECLCALLBACK(void) AudioVRDE::drvDestruct(PPDMDRVINS pDrvIns)
     482{
     483    LogFlowFuncEnter();
     484}
     485
     486/**
     487 * VRDE audio driver registration record.
     488 */
     489const PDMDRVREG AudioVRDE::DrvReg =
     490{
     491    PDM_DRVREG_VERSION,
     492    /* szName */
    1014493    "AudioVRDE",
    1015494    /* szRCMod */
     
    1018497    "",
    1019498    /* pszDescription */
    1020     "Audio VRDE",
     499    "Audio driver for VRDE backend",
    1021500    /* fFlags */
    1022501    PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
     
    1028507    sizeof(DRVAUDIOVRDE),
    1029508    /* pfnConstruct */
    1030     AudioVRDE::drvAudioVRDEConstruct,
     509    AudioVRDE::drvConstruct,
    1031510    /* pfnDestruct */
    1032     drvAudioVRDEDestruct,
     511    AudioVRDE::drvDestruct,
    1033512    /* pfnRelocate */
    1034513    NULL,
     
    1055534};
    1056535
    1057 
    1058 
  • trunk/src/VBox/Main/src-client/VBoxDriversRegister.cpp

    r50686 r53442  
    7171    if (RT_FAILURE(rc))
    7272        return rc;
     73
    7374#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    74     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvAudioVRDE);
     75    rc = pCallbacks->pfnRegister(pCallbacks, &AudioVRDE::DrvReg);
    7576#else
    7677    rc = pCallbacks->pfnRegister(pCallbacks, &AudioSniffer::DrvReg);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette