VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp@ 53877

Last change on this file since 53877 was 53831, checked in by vboxsync, 10 years ago

PDM/Audio: Build fix; forgot some files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.4 KB
Line 
1/* $Id: DrvAudioVRDE.cpp 53831 2015-01-15 16:15:21Z vboxsync $ */
2/** @file
3 * VRDE audio backend for Main.
4 */
5
6/*
7 * Copyright (C) 2013-2014 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#include "DrvAudioVRDE.h"
18#include "ConsoleImpl.h"
19#include "ConsoleVRDPServer.h"
20
21#include "Logging.h"
22
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
30#include <VBox/vmm/pdmaudioifs.h>
31#include <VBox/vmm/pdmdrv.h>
32#include <VBox/RemoteDesktop/VRDE.h>
33#include <VBox/vmm/cfgm.h>
34#include <VBox/err.h>
35
36#ifdef LOG_GROUP
37 #undef LOG_GROUP
38#endif
39#define LOG_GROUP LOG_GROUP_DEV_AUDIO
40#include <VBox/log.h>
41
42/**
43 * Audio VRDE driver instance data.
44 */
45typedef struct DRVAUDIOVRDE
46{
47 /** Pointer to audio VRDE object. */
48 AudioVRDE *pAudioVRDE;
49 PPDMDRVINS pDrvIns;
50 /** Pointer to the driver instance structure. */
51 PDMIHOSTAUDIO IHostAudioR3;
52 ConsoleVRDPServer *pConsoleVRDPServer;
53 /** Pointer to the DrvAudio port interface that is above it. */
54 PPDMIAUDIOCONNECTOR pDrvAudio;
55} DRVAUDIOVRDE, *PDRVAUDIOVRDE;
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;
73 uint64_t old_ticks;
74 uint64_t cSamplesSentPerSec;
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);
151 }
152 else
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.
171 *
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
189 /*
190 * Just call the VRDP server with the data.
191 */
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)
199 cSamplesPlayed = live;
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 pVRDEStrmOut->old_ticks = now;
207
208 int cSamplesToSend = live;
209
210/* if (!cSamplesToSend)
211 {
212 if (pcSamplesPlayed)
213 pcSamplesPlayed = 0;
214
215 return 0;
216 }*/
217
218 LogFlowFunc(("uFreq=%RU32, cChan=%RU8, cBits=%RU8, fSigned=%RTbool, enmFormat=%ld, cSamplesToSend=%RU32\n",
219 pHstStrmOut->Props.uHz, pHstStrmOut->Props.cChannels,
220 pHstStrmOut->Props.cBits, pHstStrmOut->Props.fSigned,
221 format, cSamplesToSend));
222
223 uint32_t cReadTotal = 0;
224
225 PPDMAUDIOSAMPLE pSamples;
226 uint32_t cRead;
227 int rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend,
228 &pSamples, &cRead);
229 if ( RT_SUCCESS(rc)
230 && cRead)
231 {
232 cReadTotal = cRead;
233 pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
234
235 if (rc == VINF_TRY_AGAIN)
236 {
237 rc = audioMixBufAcquire(&pHstStrmOut->MixBuf, cSamplesToSend - cRead,
238 &pSamples, &cRead);
239 if (RT_SUCCESS(rc))
240 pDrv->pConsoleVRDPServer->SendAudioSamples(pSamples, cRead, format);
241
242 cReadTotal += cRead;
243 }
244 }
245
246 audioMixBufFinish(&pHstStrmOut->MixBuf, cSamplesToSend);
247
248 /*
249 * Always report back all samples acquired, regardless of whether the
250 * VRDP server actually did process those.
251 */
252 if (pcSamplesPlayed)
253 *pcSamplesPlayed = cReadTotal;
254
255 LogFlowFunc(("cReadTotal=%RU32, rc=%Rrc\n", cReadTotal, rc));
256 return rc;
257}
258
259static DECLCALLBACK(int) drvAudioVRDEFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
260{
261 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
262 AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
263
264 if (pDrv->pConsoleVRDPServer)
265 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL);
266
267 return VINF_SUCCESS;
268}
269
270static DECLCALLBACK(int) drvAudioVRDEFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
271{
272 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
273 AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
274
275 return VINF_SUCCESS;
276}
277
278static DECLCALLBACK(int) drvAudioVRDEControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
279 PDMAUDIOSTREAMCMD enmStreamCmd)
280{
281 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
282 AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
283
284 PVRDESTREAMIN pVRDEStrmOut = (PVRDESTREAMIN)pHstStrmOut;
285 AssertPtrReturn(pVRDEStrmOut, VERR_INVALID_POINTER);
286
287 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
288
289 audioMixBufReset(&pHstStrmOut->MixBuf);
290
291 return VINF_SUCCESS;
292}
293
294static DECLCALLBACK(int) drvAudioVRDEControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
295 PDMAUDIOSTREAMCMD enmStreamCmd)
296{
297 PDRVAUDIOVRDE pDrv = RT_FROM_MEMBER(pInterface, DRVAUDIOVRDE, IHostAudioR3);
298 AssertPtrReturn(pDrv, VERR_INVALID_POINTER);
299
300 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pHstStrmIn;
301 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
302
303 PPDMAUDIOHSTSTRMIN pThisStrmIn = &pVRDEStrmIn->HstStrmIn;
304
305 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
306
307 if (!pDrv->pConsoleVRDPServer)
308 return VINF_SUCCESS;
309
310 audioMixBufReset(&pThisStrmIn->MixBuf);
311
312 /* Initialize only if not already done. */
313 if (enmStreamCmd == PDMAUDIOSTREAMCMD_ENABLE)
314 {
315 int rc2 = pDrv->pConsoleVRDPServer->SendAudioInputBegin(NULL, pVRDEStrmIn, audioMixBufSize(&pThisStrmIn->MixBuf),
316 pThisStrmIn->Props.uHz,
317 pThisStrmIn->Props.cChannels, pThisStrmIn->Props.cBits);
318#ifdef DEBUG
319 if (rc2 == VERR_NOT_SUPPORTED)
320 LogFlowFunc(("No RDP client connected, so no input recording supported\n"));
321#endif
322 }
323 else if (enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE)
324 {
325 pDrv->pConsoleVRDPServer->SendAudioInputEnd(NULL /* pvUserCtx */);
326 }
327
328 return VINF_SUCCESS;
329}
330
331static DECLCALLBACK(int) drvAudioVRDEGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
332{
333 pCfg->cbStreamOut = sizeof(VRDESTREAMOUT);
334 pCfg->cbStreamIn = sizeof(VRDESTREAMIN);
335 pCfg->cMaxHstStrmsOut = 1;
336 pCfg->cMaxHstStrmsIn = 2; /* Microphone in + line in. */
337
338 return VINF_SUCCESS;
339}
340
341/**
342 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
343 */
344static DECLCALLBACK(void *) drvAudioVRDEQueryInterface(PPDMIBASE pInterface, const char *pszIID)
345{
346 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
347 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
348
349 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
350 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudioR3);
351 return NULL;
352}
353
354AudioVRDE::AudioVRDE(Console *pConsole)
355 : mpDrv(NULL),
356 mParent(pConsole)
357{
358}
359
360AudioVRDE::~AudioVRDE(void)
361{
362 if (mpDrv)
363 {
364 mpDrv->pAudioVRDE = NULL;
365 mpDrv = NULL;
366 }
367}
368
369int AudioVRDE::onVRDEInputIntercept(bool fIntercept)
370{
371 LogFlowThisFunc(("fIntercept=%RTbool\n", fIntercept));
372
373 return VINF_SUCCESS; /* Never veto. */
374}
375
376/**
377 * Marks the beginning of sending captured audio data from a connected
378 * RDP client.
379 *
380 * @return IPRT status code.
381 * @param pvContext The context; in this case a pointer to a
382 * VRDESTREAMIN structure.
383 * @param pVRDEAudioBegin Pointer to a VRDEAUDIOINBEGIN structure.
384 */
385int AudioVRDE::onVRDEInputBegin(void *pvContext, PVRDEAUDIOINBEGIN pVRDEAudioBegin)
386{
387 AssertPtrReturn(pvContext, VERR_INVALID_POINTER);
388 AssertPtrReturn(pVRDEAudioBegin, VERR_INVALID_POINTER);
389
390 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
391 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
392
393 VRDEAUDIOFORMAT audioFmt = pVRDEAudioBegin->fmt;
394
395 int iSampleHz = VRDE_AUDIO_FMT_SAMPLE_FREQ(audioFmt);
396 int cChannels = VRDE_AUDIO_FMT_CHANNELS(audioFmt);
397 int cBits = VRDE_AUDIO_FMT_BITS_PER_SAMPLE(audioFmt);
398 bool fUnsigned = VRDE_AUDIO_FMT_SIGNED(audioFmt);
399
400 /*pVRDEStrmIn->cbSample = VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt);
401 pVRDEStrmIn->uHz = iSampleHz;*/
402
403 LogFlowFunc(("cbSample=%RU32, iSampleHz=%d, cChannels=%d, cBits=%d, fUnsigned=%RTbool\n",
404 VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(audioFmt), iSampleHz, cChannels, cBits, fUnsigned));
405
406 return VINF_SUCCESS;
407}
408
409int AudioVRDE::onVRDEInputData(void *pvContext, const void *pvData, uint32_t cbData)
410{
411 PVRDESTREAMIN pVRDEStrmIn = (PVRDESTREAMIN)pvContext;
412 AssertPtrReturn(pVRDEStrmIn, VERR_INVALID_POINTER);
413
414 PPDMAUDIOHSTSTRMIN pHstStrmIn = &pVRDEStrmIn->HstStrmIn;
415 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
416
417 /** @todo Use CritSect! */
418
419 uint32_t cWritten;
420 int rc = audioMixBufWriteCirc(&pHstStrmIn->MixBuf, pvData, cbData, &cWritten);
421 if (RT_SUCCESS(rc))
422 pVRDEStrmIn->cSamplesCaptured += cWritten;
423
424 LogFlowFunc(("cbData=%RU32, cWritten=%RU32, cSamplesCaptured=%RU32, rc=%Rrc\n",
425 cbData, cWritten, pVRDEStrmIn->cSamplesCaptured, rc));
426 return rc;
427}
428
429int AudioVRDE::onVRDEInputEnd(void *pvContext)
430{
431 NOREF(pvContext);
432
433 return VINF_SUCCESS;
434}
435
436/**
437 * Construct a VRDE audio driver instance.
438 *
439 * @copydoc FNPDMDRVCONSTRUCT
440 */
441/* static */
442DECLCALLBACK(int) AudioVRDE::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
443{
444 PDRVAUDIOVRDE pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIOVRDE);
445 LogRel(("Audio: Initializing VRDE driver\n"));
446 LogFlowFunc(("fFlags=0x%x\n", fFlags));
447
448 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
449 ("Configuration error: Not possible to attach anything to this driver!\n"),
450 VERR_PDM_DRVINS_NO_ATTACH);
451
452 /*
453 * Init the static parts.
454 */
455 pThis->pDrvIns = pDrvIns;
456 /* IBase */
457 pDrvIns->IBase.pfnQueryInterface = drvAudioVRDEQueryInterface;
458 /* IHostAudioR3 */
459 pThis->IHostAudioR3.pfnInitIn = drvAudioVRDEInitIn;
460 pThis->IHostAudioR3.pfnInitOut = drvAudioVRDEInitOut;
461 pThis->IHostAudioR3.pfnControlOut = drvAudioVRDEControlOut;
462 pThis->IHostAudioR3.pfnControlIn = drvAudioVRDEControlIn;
463 pThis->IHostAudioR3.pfnFiniIn = drvAudioVRDEFiniIn;
464 pThis->IHostAudioR3.pfnFiniOut = drvAudioVRDEFiniOut;
465 pThis->IHostAudioR3.pfnCaptureIn = drvAudioVRDECaptureIn;
466 pThis->IHostAudioR3.pfnPlayOut = drvAudioVRDEPlayOut;
467 pThis->IHostAudioR3.pfnGetConf = drvAudioVRDEGetConf;
468 pThis->IHostAudioR3.pfnInit = drvAudioVRDEInit;
469
470 /* Get VRDPServer pointer. */
471 void *pvUser;
472 int rc = CFGMR3QueryPtr(pCfg, "ObjectVRDPServer", &pvUser);
473 if (RT_FAILURE(rc))
474 {
475 AssertMsgFailed(("Confguration error: No/bad \"ObjectVRDPServer\" value, rc=%Rrc\n", rc));
476 return rc;
477 }
478
479 /* CFGM tree saves the pointer to ConsoleVRDPServer in the Object node of AudioVRDE. */
480 pThis->pConsoleVRDPServer = (ConsoleVRDPServer *)pvUser;
481
482 pvUser = NULL;
483 rc = CFGMR3QueryPtr(pCfg, "Object", &pvUser);
484 if (RT_FAILURE(rc))
485 {
486 AssertMsgFailed(("Confguration error: No/bad \"Object\" value, rc=%Rrc\n", rc));
487 return rc;
488 }
489
490 pThis->pAudioVRDE = (AudioVRDE *)pvUser;
491 pThis->pAudioVRDE->mpDrv = pThis;
492
493 /*
494 * Get the interface for the above driver (DrvAudio) to make mixer/conversion calls.
495 * Described in CFGM tree.
496 */
497 pThis->pDrvAudio = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIAUDIOCONNECTOR);
498 if (!pThis->pDrvAudio)
499 {
500 AssertMsgFailed(("Configuration error: No upper interface specified!\n"));
501 return VERR_PDM_MISSING_INTERFACE_ABOVE;
502 }
503
504 return VINF_SUCCESS;
505}
506
507/* static */
508DECLCALLBACK(void) AudioVRDE::drvDestruct(PPDMDRVINS pDrvIns)
509{
510 LogFlowFuncEnter();
511}
512
513/**
514 * VRDE audio driver registration record.
515 */
516const PDMDRVREG AudioVRDE::DrvReg =
517{
518 PDM_DRVREG_VERSION,
519 /* szName */
520 "AudioVRDE",
521 /* szRCMod */
522 "",
523 /* szR0Mod */
524 "",
525 /* pszDescription */
526 "Audio driver for VRDE backend",
527 /* fFlags */
528 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
529 /* fClass. */
530 PDM_DRVREG_CLASS_AUDIO,
531 /* cMaxInstances */
532 ~0U,
533 /* cbInstance */
534 sizeof(DRVAUDIOVRDE),
535 /* pfnConstruct */
536 AudioVRDE::drvConstruct,
537 /* pfnDestruct */
538 AudioVRDE::drvDestruct,
539 /* pfnRelocate */
540 NULL,
541 /* pfnIOCtl */
542 NULL,
543 /* pfnPowerOn */
544 NULL,
545 /* pfnReset */
546 NULL,
547 /* pfnSuspend */
548 NULL,
549 /* pfnResume */
550 NULL,
551 /* pfnAttach */
552 NULL,
553 /* pfnDetach */
554 NULL,
555 /* pfnPowerOff */
556 NULL,
557 /* pfnSoftReset */
558 NULL,
559 /* u32EndVersion */
560 PDM_DRVREG_VERSION
561};
562
Note: See TracBrowser for help on using the repository browser.

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