VirtualBox

Changeset 88460 in vbox


Ignore:
Timestamp:
Apr 12, 2021 10:51:18 AM (3 years ago)
Author:
vboxsync
Message:

DrvAudioVRDE: Cleanup. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r88390 r88460  
    4444*********************************************************************************************************************************/
    4545/**
    46  * Audio VRDE driver instance data.
     46 * VRDE stream.
     47 */
     48typedef struct VRDESTREAM
     49{
     50    /** The stream's acquired configuration. */
     51    PDMAUDIOSTREAMCFG   Cfg;
     52    union
     53    {
     54        struct
     55        {
     56            /** Circular buffer for holding the recorded audio frames from the host. */
     57            PRTCIRCBUF  pCircBuf;
     58        } In;
     59    };
     60} VRDESTREAM;
     61/** Pointer to a VRDE stream. */
     62typedef VRDESTREAM *PVRDESTREAM;
     63
     64/**
     65 * VRDE (host) audio driver instance data.
    4766 */
    4867typedef struct DRVAUDIOVRDE
     
    5271    /** Pointer to the driver instance structure. */
    5372    PPDMDRVINS           pDrvIns;
    54     /** Pointer to host audio interface. */
    55     PDMIHOSTAUDIO        IHostAudio;
    5673    /** Pointer to the VRDP's console object. */
    5774    ConsoleVRDPServer   *pConsoleVRDPServer;
     
    6077    /** Number of connected clients to this VRDE instance. */
    6178    uint32_t             cClients;
    62 } DRVAUDIOVRDE, *PDRVAUDIOVRDE;
    63 
    64 typedef struct VRDESTREAM
    65 {
    66     /** The stream's acquired configuration. */
    67     PPDMAUDIOSTREAMCFG pCfg;
    68     union
    69     {
    70         struct
    71         {
    72             /** Circular buffer for holding the recorded audio frames from the host. */
    73             PRTCIRCBUF  pCircBuf;
    74         } In;
    75     };
    76 } VRDESTREAM, *PVRDESTREAM;
     79    /** Pointer to host audio interface. */
     80    PDMIHOSTAUDIO        IHostAudio;
     81} DRVAUDIOVRDE;
     82/** Pointer to the instance data for an VRDE audio driver. */
     83typedef DRVAUDIOVRDE *PDRVAUDIOVRDE;
    7784
    7885/* Sanity. */
    7986AssertCompileSize(PDMAUDIOFRAME, sizeof(int64_t) * 2 /* st_sample_t using by VRDP server */);
    8087
    81 static int vrdeCreateStreamIn(PVRDESTREAM pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    82 {
    83     RT_NOREF(pCfgReq);
    84     AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
    85 
     88
     89
     90/*********************************************************************************************************************************
     91*   Class AudioVRDE                                                                                                              *
     92*********************************************************************************************************************************/
     93
     94AudioVRDE::AudioVRDE(Console *pConsole)
     95    : AudioDriver(pConsole)
     96    , mpDrv(NULL)
     97{
     98}
     99
     100
     101AudioVRDE::~AudioVRDE(void)
     102{
     103    if (mpDrv)
     104    {
     105        mpDrv->pAudioVRDE = NULL;
     106        mpDrv = NULL;
     107    }
     108}
     109
     110
     111/**
     112 * @copydoc AudioDriver::configureDriver
     113 */
     114int AudioVRDE::configureDriver(PCFGMNODE pLunCfg)
     115{
     116    int rc = CFGMR3InsertInteger(pLunCfg, "Object", (uintptr_t)this);
     117    AssertRCReturn(rc, rc);
     118    CFGMR3InsertInteger(pLunCfg, "ObjectVRDPServer", (uintptr_t)mpConsole->i_consoleVRDPServer());
     119    AssertRCReturn(rc, rc);
     120
     121    return AudioDriver::configureDriver(pLunCfg);
     122}
     123
     124
     125void AudioVRDE::onVRDEClientConnect(uint32_t uClientID)
     126{
     127    RT_NOREF(uClientID);
     128
     129    LogRel2(("Audio: VRDE client connected\n"));
     130    if (mpDrv)
     131        mpDrv->cClients++;
     132}
     133
     134
     135void AudioVRDE::onVRDEClientDisconnect(uint32_t uClientID)
     136{
     137    RT_NOREF(uClientID);
     138
     139    LogRel2(("Audio: VRDE client disconnected\n"));
     140    Assert(mpDrv->cClients);
     141    if (mpDrv)
     142        mpDrv->cClients--;
     143}
     144
     145
     146int AudioVRDE::onVRDEControl(bool fEnable, uint32_t uFlags)
     147{
     148    RT_NOREF(fEnable, uFlags);
     149    LogFlowThisFunc(("fEnable=%RTbool, uFlags=0x%x\n", fEnable, uFlags));
     150
     151    if (mpDrv == NULL)
     152        return VERR_INVALID_STATE;
     153
     154    return VINF_SUCCESS; /* Never veto. */
     155}
     156
     157
     158/**
     159 * Marks the beginning of sending captured audio data from a connected
     160 * RDP client.
     161 *
     162 * @returns VBox status code.
     163 * @param   pvContext               The context; in this case a pointer to a
     164 *                                  VRDESTREAMIN structure.
     165 * @param   pVRDEAudioBegin         Pointer to a VRDEAUDIOINBEGIN structure.
     166 */
     167int AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
     168{
     169    AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
     170    AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
     171    PVRDESTREAM pVRDEStrmIn = (PVRDESTREAM)pvContext;
     172    AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
     173
     174#ifdef LOG_ENABLED
     175    VRDEAUDIOFORMAT const audioFmt = pVRDEAudioBegin->fmt;
     176    LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
     177                 VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt),
     178                 VRDE_AUDIO_FMT_CHANNELS(audioFmt), VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt), VRDE_AUDIO_FMT_SIGNED(audioFmt)));
     179#endif
     180
     181    return VINF_SUCCESS;
     182}
     183
     184
     185int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
     186{
     187    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pvContext;
     188    AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
     189
     190    void  *pvBuf = NULL;
     191    size_t cbBuf = 0;
     192    RTCircBufAcquireWriteBlock(pStreamVRDE->In.pCircBuf, cbData, &pvBuf, &cbBuf);
     193
     194    if (cbBuf)
     195        memcpy(pvBuf, pvData, cbBuf);
     196
     197    RTCircBufReleaseWriteBlock(pStreamVRDE->In.pCircBuf, cbBuf);
     198
     199    if (cbBuf < cbData)
     200        LogRelMax(999, ("VRDE: Capturing audio data lost %zu bytes\n", cbData - cbBuf)); /** @todo Use an error counter. */
     201
     202    return VINF_SUCCESS; /** @todo r=andy How to tell the caller if we were not able to handle *all* input data? */
     203}
     204
     205
     206int AudioVRDE::onVRDEInputEnd(void *pvContext)
     207{
     208    RT_NOREF(pvContext);
     209    return VINF_SUCCESS;
     210}
     211
     212
     213int AudioVRDE::onVRDEInputIntercept(bool fEnabled)
     214{
     215    RT_NOREF(fEnabled);
     216    return VINF_SUCCESS; /* Never veto. */
     217}
     218
     219
     220
     221/*********************************************************************************************************************************
     222*   PDMIHOSTAUDIO                                                                                                                *
     223*********************************************************************************************************************************/
     224
     225/**
     226 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
     227 */
     228static DECLCALLBACK(int) drvAudioVrdeHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
     229{
     230    RT_NOREF(pInterface);
     231    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
     232
     233    RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "VRDE");
     234    pBackendCfg->cbStreamOut    = sizeof(VRDESTREAM);
     235    pBackendCfg->cbStreamIn     = sizeof(VRDESTREAM);
     236    pBackendCfg->cMaxStreamsIn  = UINT32_MAX;
     237    pBackendCfg->cMaxStreamsOut = UINT32_MAX;
     238
     239    return VINF_SUCCESS;
     240}
     241
     242
     243/**
     244 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
     245 */
     246static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvAudioVrdeHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     247{
     248    RT_NOREF(pInterface, enmDir);
     249    return PDMAUDIOBACKENDSTS_RUNNING;
     250}
     251
     252
     253static int vrdeCreateStreamIn(PVRDESTREAM pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgAcq)
     254{
    86255    /*
    87256     * The VRDP server does its own mixing and resampling as it may server
     
    111280
    112281
    113 static int vrdeCreateStreamOut(PVRDESTREAM pStreamVRDE, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    114 {
    115     RT_NOREF(pStreamVRDE, pCfgReq);
    116     AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
    117 
     282static int vrdeCreateStreamOut(PPDMAUDIOSTREAMCFG pCfgAcq)
     283{
    118284    /*
    119285     * The VRDP server does its own mixing and resampling because it may be
     
    139305
    140306
    141 static int vrdeControlStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE, PDMAUDIOSTREAMCMD enmStreamCmd)
    142 {
    143     RT_NOREF(pDrv, pStreamVRDE, enmStreamCmd);
    144 
    145     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
    146 
    147     return VINF_SUCCESS;
    148 }
    149 
    150 
    151 static int vrdeControlStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE, PDMAUDIOSTREAMCMD enmStreamCmd)
    152 {
    153     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
    154 
     307/**
     308 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
     309 */
     310static DECLCALLBACK(int) drvAudioVrdeHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     311                                                     PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
     312{
     313    RT_NOREF(pInterface);
     314    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
     315    AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
     316    AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
     317    AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
     318
     319    int rc;
     320    if (pCfgReq->enmDir == PDMAUDIODIR_IN)
     321        rc = vrdeCreateStreamIn(pStreamVRDE, pCfgAcq);
     322    else
     323        rc = vrdeCreateStreamOut(pCfgAcq);
     324    PDMAudioStrmCfgCopy(&pStreamVRDE->Cfg, pCfgAcq);
     325    return rc;
     326}
     327
     328
     329/**
     330 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
     331 */
     332static DECLCALLBACK(int) drvAudioVrdeHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     333{
     334    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     335    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     336    AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
     337
     338    if (pStreamVRDE->Cfg.enmDir == PDMAUDIODIR_OUT)
     339    {
     340        if (pDrv->pConsoleVRDPServer)
     341            pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
     342
     343        if (pStreamVRDE->In.pCircBuf)
     344        {
     345            RTCircBufDestroy(pStreamVRDE->In.pCircBuf);
     346            pStreamVRDE->In.pCircBuf = NULL;
     347        }
     348    }
     349    pDrv->pConsoleVRDPServer = NULL;
     350
     351    return VINF_SUCCESS;
     352}
     353
     354
     355/**
     356 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable}
     357 */
     358static DECLCALLBACK(int) drvAudioVrdeHA_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     359{
     360    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     361    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     362
     363    int rc;
    155364    if (!pDrv->pConsoleVRDPServer)
    156365    {
    157         LogRel(("Audio: VRDP console not ready yet\n"));
     366        LogRelMax(32, ("Audio: VRDP console not ready (enable)\n"));
     367        rc = VERR_AUDIO_STREAM_NOT_READY;
     368    }
     369    else if (pStreamVRDE->Cfg.enmDir == PDMAUDIODIR_IN)
     370    {
     371        rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pStreamVRDE,
     372                                                           PDMAudioPropsMilliToFrames(&pStreamVRDE->Cfg.Props, 200 /*ms*/),
     373                                                           PDMAudioPropsHz(&pStreamVRDE->Cfg.Props),
     374                                                           PDMAudioPropsChannels(&pStreamVRDE->Cfg.Props),
     375                                                           PDMAudioPropsSampleBits(&pStreamVRDE->Cfg.Props));
     376        if (rc == VERR_NOT_SUPPORTED)
     377        {
     378            LogRelMax(64, ("Audio: No VRDE client connected, so no input recording available\n"));
     379            rc = VERR_AUDIO_STREAM_NOT_READY;
     380        }
     381    }
     382    else
     383        rc = VINF_SUCCESS;
     384    LogFlowFunc(("returns %Rrc\n", rc));
     385    return rc;
     386}
     387
     388
     389/**
     390 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDisable}
     391 */
     392static DECLCALLBACK(int) drvAudioVrdeHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     393{
     394    PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     395    PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
     396
     397    int rc;
     398    if (!pDrv->pConsoleVRDPServer)
     399    {
     400        LogRelMax(32, ("Audio: VRDP console not ready (disable)\n"));
     401        rc = VERR_AUDIO_STREAM_NOT_READY;
     402    }
     403    else if (pStreamVRDE->Cfg.enmDir == PDMAUDIODIR_IN)
     404    {
     405        pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
     406        rc = VINF_SUCCESS;
     407    }
     408    else
     409        rc = VINF_SUCCESS;
     410    LogFlowFunc(("returns %Rrc\n", rc));
     411    return rc;
     412}
     413
     414
     415/**
     416 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamPause}
     417 */
     418static DECLCALLBACK(int) drvAudioVrdeHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     419{
     420    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     421    RT_NOREF(pStream);
     422
     423    if (!pDrv->pConsoleVRDPServer)
     424    {
     425        LogRelMax(32, ("Audio: VRDP console not ready (pause)\n"));
    158426        return VERR_AUDIO_STREAM_NOT_READY;
    159427    }
    160 
    161     int rc;
    162 
    163     /* Initialize only if not already done. */
     428    LogFlowFunc(("returns VINF_SUCCESS\n"));
     429    return VINF_SUCCESS;
     430}
     431
     432
     433/**
     434 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamResume}
     435 */
     436static DECLCALLBACK(int) drvAudioVrdeHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     437{
     438    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     439    RT_NOREF(pStream);
     440
     441    if (!pDrv->pConsoleVRDPServer)
     442    {
     443        LogRelMax(32, ("Audio: VRDP console not ready (resume)\n"));
     444        return VERR_AUDIO_STREAM_NOT_READY;
     445    }
     446    LogFlowFunc(("returns VINF_SUCCESS\n"));
     447    return VINF_SUCCESS;
     448}
     449
     450
     451/**
     452 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain}
     453 */
     454static DECLCALLBACK(int) drvAudioVrdeHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     455{
     456    RT_NOREF(pInterface, pStream);
     457    LogFlowFunc(("returns VINF_SUCCESS\n"));
     458    return VINF_SUCCESS;
     459}
     460
     461
     462/**
     463 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
     464 */
     465static DECLCALLBACK(int) drvAudioVrdeHA_StreamControl(PPDMIHOSTAUDIO pInterface,
     466                                                      PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     467{
     468    /** @todo r=bird: I'd like to get rid of this pfnStreamControl method,
     469     *        replacing it with individual StreamXxxx methods.  That would save us
     470     *        potentally huge switches and more easily see which drivers implement
     471     *        which operations (grep for pfnStreamXxxx). */
    164472    switch (enmStreamCmd)
    165473    {
    166474        case PDMAUDIOSTREAMCMD_ENABLE:
    167         {
    168             rc = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pStreamVRDE,
    169                                                                PDMAudioPropsMilliToFrames(&pStreamVRDE->pCfg->Props, 200 /*ms*/),
    170                                                                PDMAudioPropsHz(&pStreamVRDE->pCfg->Props),
    171                                                                PDMAudioPropsChannels(&pStreamVRDE->pCfg->Props),
    172                                                                PDMAudioPropsSampleBits(&pStreamVRDE->pCfg->Props));
    173             if (rc == VERR_NOT_SUPPORTED)
    174             {
    175                 LogRel(("Audio: No VRDE client connected, so no input recording available\n"));
    176                 rc = VERR_AUDIO_STREAM_NOT_READY;
    177             }
    178 
     475            return drvAudioVrdeHA_StreamEnable(pInterface, pStream);
     476        case PDMAUDIOSTREAMCMD_DISABLE:
     477            return drvAudioVrdeHA_StreamDisable(pInterface, pStream);
     478        case PDMAUDIOSTREAMCMD_PAUSE:
     479            return drvAudioVrdeHA_StreamPause(pInterface, pStream);
     480        case PDMAUDIOSTREAMCMD_RESUME:
     481            return drvAudioVrdeHA_StreamResume(pInterface, pStream);
     482        case PDMAUDIOSTREAMCMD_DRAIN:
     483            return drvAudioVrdeHA_StreamDrain(pInterface, pStream);
     484
     485        case PDMAUDIOSTREAMCMD_END:
     486        case PDMAUDIOSTREAMCMD_32BIT_HACK:
     487        case PDMAUDIOSTREAMCMD_INVALID:
     488            /* no default*/
    179489            break;
    180         }
    181 
    182         case PDMAUDIOSTREAMCMD_DISABLE:
    183         {
    184             pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
    185             rc = VINF_SUCCESS;
    186 
    187             break;
    188         }
    189 
    190         case PDMAUDIOSTREAMCMD_PAUSE:
    191         {
    192             rc = VINF_SUCCESS;
    193             break;
    194         }
    195 
    196         case PDMAUDIOSTREAMCMD_RESUME:
    197         {
    198             rc = VINF_SUCCESS;
    199             break;
    200         }
    201 
    202         default:
    203         {
    204             rc = VERR_NOT_SUPPORTED;
    205             break;
    206         }
    207     }
    208 
    209     if (RT_FAILURE(rc))
    210         LogFunc(("Failed with %Rrc\n", rc));
    211 
    212     return rc;
    213 }
    214 
    215 /**
    216  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
    217  */
    218 static DECLCALLBACK(int) drvAudioVrdeHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    219                                                       void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
    220 {
    221     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    222     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    223     AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
    224     AssertReturn(uBufSize,         VERR_INVALID_PARAMETER);
    225     /* puRead is optional. */
    226 
     490    }
     491    return VERR_NOT_SUPPORTED;
     492}
     493
     494
     495/**
     496 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
     497 */
     498static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     499{
     500    RT_NOREF(pInterface);
    227501    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
    228502
    229     size_t cbData = 0;
    230 
    231     if (RTCircBufUsed(pStreamVRDE->In.pCircBuf))
    232     {
    233         void *pvData;
    234 
    235         RTCircBufAcquireReadBlock(pStreamVRDE->In.pCircBuf, uBufSize, &pvData, &cbData);
    236 
    237         if (cbData)
    238             memcpy(pvBuf, pvData, cbData);
    239 
    240         RTCircBufReleaseReadBlock(pStreamVRDE->In.pCircBuf, cbData);
    241     }
    242 
    243     if (puRead)
    244         *puRead = (uint32_t)cbData;
    245 
    246     return VINF_SUCCESS;
     503    if (pStreamVRDE->Cfg.enmDir == PDMAUDIODIR_IN)
     504    {
     505        /* Return frames instead of bytes here
     506         * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout). */
     507        return (uint32_t)PDMAudioPropsBytesToFrames(&pStreamVRDE->Cfg.Props, RTCircBufUsed(pStreamVRDE->In.pCircBuf));
     508    }
     509    return 0;
     510}
     511
     512
     513/**
     514 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
     515 */
     516static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     517{
     518    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     519    RT_NOREF(pStream);
     520
     521    /** @todo Find some sane value here. We probably need a VRDE API VRDE to specify this. */
     522    if (pDrv->cClients)
     523        return _16K * sizeof(PDMAUDIOFRAME);
     524    return 0;
     525}
     526
     527
     528/**
     529 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
     530 */
     531static DECLCALLBACK(PDMAUDIOSTREAMSTS) drvAudioVrdeHA_StreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     532{
     533    PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
     534    RT_NOREF(pStream);
     535
     536    PDMAUDIOSTREAMSTS fStrmStatus = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
     537
     538    if (pDrv->cClients) /* If any clients are connected, flag the stream as enabled. */
     539       fStrmStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
     540
     541    return fStrmStatus;
    247542}
    248543
     
    266561
    267562    /* Prepate the format. */
    268     PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->pCfg->Props;
     563    PPDMAUDIOPCMPROPS pProps = &pStreamVRDE->Cfg.Props;
    269564    VRDEAUDIOFORMAT const uVrdpFormat = VRDE_AUDIO_FMT_MAKE(PDMAudioPropsHz(pProps),
    270565                                                            PDMAudioPropsChannels(pProps),
     
    307602
    308603
    309 static int vrdeDestroyStreamIn(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE)
    310 {
    311     if (pDrv->pConsoleVRDPServer)
    312         pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
    313 
    314     if (pStreamVRDE->In.pCircBuf)
    315     {
    316         RTCircBufDestroy(pStreamVRDE->In.pCircBuf);
    317         pStreamVRDE->In.pCircBuf = NULL;
    318     }
    319 
    320     return VINF_SUCCESS;
    321 }
    322 
    323 
    324 static int vrdeDestroyStreamOut(PDRVAUDIOVRDE pDrv, PVRDESTREAM pStreamVRDE)
    325 {
    326     RT_NOREF(pDrv, pStreamVRDE);
    327 
    328     return VINF_SUCCESS;
    329 }
    330 
    331 
    332 /**
    333  * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
    334  */
    335 static DECLCALLBACK(int) drvAudioVrdeHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
     604/**
     605 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
     606 */
     607static DECLCALLBACK(int) drvAudioVrdeHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     608                                                      void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    336609{
    337610    RT_NOREF(pInterface);
    338     AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    339 
    340     RTStrPrintf2(pBackendCfg->szName, sizeof(pBackendCfg->szName), "VRDE");
    341 
    342     pBackendCfg->cbStreamOut    = sizeof(VRDESTREAM);
    343     pBackendCfg->cbStreamIn     = sizeof(VRDESTREAM);
    344     pBackendCfg->cMaxStreamsIn  = UINT32_MAX;
    345     pBackendCfg->cMaxStreamsOut = UINT32_MAX;
    346 
    347     return VINF_SUCCESS;
    348 }
    349 
    350 
    351 /**
    352  * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
    353  */
    354 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvAudioVrdeHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    355 {
    356     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    357     AssertPtrReturn(pDrv, PDMAUDIOBACKENDSTS_ERROR);
    358 
    359     RT_NOREF(enmDir);
    360 
    361     return PDMAUDIOBACKENDSTS_RUNNING;
    362 }
    363 
    364 
    365 /**
    366  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    367  */
    368 static DECLCALLBACK(int) drvAudioVrdeHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
    369                                                      PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
    370 {
    371     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    372     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    373     AssertPtrReturn(pCfgReq,    VERR_INVALID_POINTER);
    374     AssertPtrReturn(pCfgAcq,    VERR_INVALID_POINTER);
    375 
    376     RT_NOREF(pInterface);
    377 
    378611    PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
    379 
    380     int rc;
    381     if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    382         rc = vrdeCreateStreamIn( pStreamVRDE, pCfgReq, pCfgAcq);
    383     else
    384         rc = vrdeCreateStreamOut(pStreamVRDE, pCfgReq, pCfgAcq);
    385 
    386     if (RT_SUCCESS(rc))
    387     {
    388         pStreamVRDE->pCfg = PDMAudioStrmCfgDup(pCfgAcq);
    389         if (!pStreamVRDE->pCfg)
    390             rc = VERR_NO_MEMORY;
    391     }
    392 
    393     return rc;
    394 }
    395 
    396 
    397 /**
    398  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
    399  */
    400 static DECLCALLBACK(int) drvAudioVrdeHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    401 {
    402     RT_NOREF(pInterface);
    403     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    404 
    405     PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    406     PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
    407 
    408     if (!pStreamVRDE->pCfg) /* Not (yet) configured? Skip. */
    409         return VINF_SUCCESS;
    410 
    411     int rc;
    412     if (pStreamVRDE->pCfg->enmDir == PDMAUDIODIR_IN)
    413         rc = vrdeDestroyStreamIn(pDrv, pStreamVRDE);
    414     else
    415         rc = vrdeDestroyStreamOut(pDrv, pStreamVRDE);
    416 
    417     if (RT_SUCCESS(rc))
    418     {
    419         PDMAudioStrmCfgFree(pStreamVRDE->pCfg);
    420         pStreamVRDE->pCfg = NULL;
    421     }
    422 
    423     return rc;
    424 }
    425 
    426 
    427 /**
    428  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
    429  */
    430 static DECLCALLBACK(int) drvAudioVrdeHA_StreamControl(PPDMIHOSTAUDIO pInterface,
    431                                                       PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    432 {
    433     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    434     AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    435 
    436     PDRVAUDIOVRDE pDrv        = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    437     PVRDESTREAM   pStreamVRDE = (PVRDESTREAM)pStream;
    438 
    439     if (!pStreamVRDE->pCfg) /* Not (yet) configured? Skip. */
    440         return VINF_SUCCESS;
    441 
    442     int rc;
    443     if (pStreamVRDE->pCfg->enmDir == PDMAUDIODIR_IN)
    444         rc = vrdeControlStreamIn(pDrv, pStreamVRDE, enmStreamCmd);
    445     else
    446         rc = vrdeControlStreamOut(pDrv, pStreamVRDE, enmStreamCmd);
    447 
    448     return rc;
    449 }
    450 
    451 
    452 /**
    453  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
    454  */
    455 static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    456 {
    457     RT_NOREF(pInterface);
    458 
    459     PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pStream;
    460 
    461     if (pStreamVRDE->pCfg->enmDir == PDMAUDIODIR_IN)
    462     {
    463         /* Return frames instead of bytes here
    464          * (since we specified PDMAUDIOSTREAMLAYOUT_RAW as the audio data layout). */
    465         return (uint32_t)PDMAUDIOSTREAMCFG_B2F(pStreamVRDE->pCfg, RTCircBufUsed(pStreamVRDE->In.pCircBuf));
    466     }
    467 
    468     return 0;
    469 }
    470 
    471 
    472 /**
    473  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
    474  */
    475 static DECLCALLBACK(uint32_t) drvAudioVrdeHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    476 {
    477     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    478     RT_NOREF(pStream);
    479 
    480     /** @todo Find some sane value here. We probably need a VRDE API VRDE to specify this. */
    481     if (pDrv->cClients)
    482         return _16K * sizeof(PDMAUDIOFRAME);
    483     return 0;
    484 }
    485 
    486 
    487 /**
    488  * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
    489  */
    490 static DECLCALLBACK(PDMAUDIOSTREAMSTS) drvAudioVrdeHA_StreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
    491 {
    492     PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudio);
    493     RT_NOREF(pStream);
    494 
    495     PDMAUDIOSTREAMSTS fStrmStatus = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;
    496 
    497     if (pDrv->cClients) /* If any clients are connected, flag the stream as enabled. */
    498        fStrmStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
    499 
    500     return fStrmStatus;
    501 }
    502 
     612    AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
     613    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     614    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
     615    AssertPtrReturn(pcbRead, VERR_INVALID_PARAMETER);
     616
     617    size_t cbData = 0;
     618    if (RTCircBufUsed(pStreamVRDE->In.pCircBuf))
     619    {
     620        void *pvData = NULL;
     621        RTCircBufAcquireReadBlock(pStreamVRDE->In.pCircBuf, cbBuf, &pvData, &cbData);
     622
     623        if (cbData)
     624            memcpy(pvBuf, pvData, cbData);
     625
     626        RTCircBufReleaseReadBlock(pStreamVRDE->In.pCircBuf, cbData);
     627    }
     628
     629    *pcbRead = (uint32_t)cbData;
     630    return VINF_SUCCESS;
     631}
     632
     633
     634/*********************************************************************************************************************************
     635*   PDMIBASE                                                                                                                     *
     636*********************************************************************************************************************************/
    503637
    504638/**
     
    516650
    517651
    518 AudioVRDE::AudioVRDE(Console *pConsole)
    519     : AudioDriver(pConsole)
    520     , mpDrv(NULL)
    521 {
    522 }
    523 
    524 
    525 AudioVRDE::~AudioVRDE(void)
    526 {
    527     if (mpDrv)
    528     {
    529         mpDrv->pAudioVRDE = NULL;
    530         mpDrv = NULL;
    531     }
    532 }
    533 
    534 
    535 /**
    536  * @copydoc AudioDriver::configureDriver
    537  */
    538 int AudioVRDE::configureDriver(PCFGMNODE pLunCfg)
    539 {
    540     int rc = CFGMR3InsertInteger(pLunCfg, "Object", (uintptr_t)this);
    541     AssertRCReturn(rc, rc);
    542     CFGMR3InsertInteger(pLunCfg, "ObjectVRDPServer", (uintptr_t)mpConsole->i_consoleVRDPServer());
    543     AssertRCReturn(rc, rc);
    544 
    545     return AudioDriver::configureDriver(pLunCfg);
    546 }
    547 
    548 
    549 void AudioVRDE::onVRDEClientConnect(uint32_t uClientID)
    550 {
    551     RT_NOREF(uClientID);
    552 
    553     LogRel2(("Audio: VRDE client connected\n"));
    554     if (mpDrv)
    555         mpDrv->cClients++;
    556 }
    557 
    558 
    559 void AudioVRDE::onVRDEClientDisconnect(uint32_t uClientID)
    560 {
    561     RT_NOREF(uClientID);
    562 
    563     LogRel2(("Audio: VRDE client disconnected\n"));
    564     Assert(mpDrv->cClients);
    565     if (mpDrv)
    566         mpDrv->cClients--;
    567 }
    568 
    569 
    570 int AudioVRDE::onVRDEControl(bool fEnable, uint32_t uFlags)
    571 {
    572     RT_NOREF(fEnable, uFlags);
    573     LogFlowThisFunc(("fEnable=%RTbool, uFlags=0x%x\n", fEnable, uFlags));
    574 
    575     if (mpDrv == NULL)
    576         return VERR_INVALID_STATE;
    577 
    578     return VINF_SUCCESS; /* Never veto. */
    579 }
    580 
    581 
    582 /**
    583  * Marks the beginning of sending captured audio data from a connected
    584  * RDP client.
    585  *
    586  * @returns VBox status code.
    587  * @param   pvContext               The context; in this case a pointer to a
    588  *                                  VRDESTREAMIN structure.
    589  * @param   pVRDEAudioBegin         Pointer to a VRDEAUDIOINBEGIN structure.
    590  */
    591 int AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
    592 {
    593     AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
    594     AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
    595 
    596     PVRDESTREAM pVRDEStrmIn = (PVRDESTREAM)pvContext;
    597     AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
    598 
    599     VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
    600 
    601     int iSampleHz  = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);     RT_NOREF(iSampleHz);
    602     int cChannels  = VRDE_AUDIO_FMT_CHANNELS(audioFmt);        RT_NOREF(cChannels);
    603     int cBits      = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt); RT_NOREF(cBits);
    604     bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);          RT_NOREF(fUnsigned);
    605 
    606     LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
    607                  VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), iSampleHz, cChannels, cBits, fUnsigned));
    608 
    609     return VINF_SUCCESS;
    610 }
    611 
    612 
    613 int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
    614 {
    615     PVRDESTREAM pStreamVRDE = (PVRDESTREAM)pvContext;
    616     AssertPtrReturn(pStreamVRDE, VERR_INVALID_POINTER);
    617 
    618     void  *pvBuf;
    619     size_t cbBuf;
    620 
    621     RTCircBufAcquireWriteBlock(pStreamVRDE->In.pCircBuf, cbData, &pvBuf, &cbBuf);
    622 
    623     if (cbBuf)
    624         memcpy(pvBuf, pvData, cbBuf);
    625 
    626     RTCircBufReleaseWriteBlock(pStreamVRDE->In.pCircBuf, cbBuf);
    627 
    628     if (cbBuf < cbData)
    629         LogRel(("VRDE: Capturing audio data lost %zu bytes\n", cbData - cbBuf)); /** @todo Use an error counter. */
    630 
    631     return VINF_SUCCESS; /** @todo r=andy How to tell the caller if we were not able to handle *all* input data? */
    632 }
    633 
    634 
    635 int AudioVRDE::onVRDEInputEnd(void *pvContext)
    636 {
    637     RT_NOREF(pvContext);
    638 
    639     return VINF_SUCCESS;
    640 }
    641 
    642 
    643 int AudioVRDE::onVRDEInputIntercept(bool fEnabled)
    644 {
    645     RT_NOREF(fEnabled);
    646     return VINF_SUCCESS; /* Never veto. */
    647 }
    648 
     652/*********************************************************************************************************************************
     653*   PDMDRVREG                                                                                                                    *
     654*********************************************************************************************************************************/
    649655
    650656/**
     
    737743    /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
    738744    pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser;
     745    AssertLogRelMsgReturn(RT_VALID_PTR(pThis->pConsoleVRDPServer) || !pThis->pConsoleVRDPServer,
     746                          ("pConsoleVRDPServer=%p\n", pThis->pConsoleVRDPServer), VERR_INVALID_POINTER);
    739747    pThis->cClients = 0;
    740748
     
    747755
    748756    pThis->pAudioVRDE = (AudioVRDE *)pvUser;
     757    AssertLogRelMsgReturn(RT_VALID_PTR(pThis->pAudioVRDE), ("pAudioVRDE=%p\n", pThis->pAudioVRDE), VERR_INVALID_POINTER);
    749758    pThis->pAudioVRDE->mpDrv = pThis;
    750759
Note: See TracChangeset for help on using the changeset viewer.

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