VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostDebugAudio.cpp@ 82254

最後變更 在這個檔案從82254是 82254,由 vboxsync 提交於 5 年 前

vmm/pdmaudioifs.h: The prefix 'cf' reads 'count-of-flags', so if you want 'count-of-frames' in a non-confusing way you have to spell it out. The prefix 'cx' means 'count-of-x-coordinates', i.e. width in pixels, and is not in any way suited to combine 'cb' and 'cFrames' in this context (PDM). bugref:9218

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 11.6 KB
 
1/* $Id: DrvHostDebugAudio.cpp 82254 2019-11-27 22:09:17Z vboxsync $ */
2/** @file
3 * Debug audio driver.
4 *
5 * Host backend for dumping and injecting audio data from/to the device emulation.
6 */
7
8/*
9 * Copyright (C) 2016-2019 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.alldomusa.eu.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include <iprt/alloc.h>
21#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
22
23#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
24#include <VBox/log.h>
25#include <VBox/vmm/pdmaudioifs.h>
26
27#include "DrvAudio.h"
28#include "VBoxDD.h"
29
30
31/**
32 * Structure for keeping a debug input/output stream.
33 */
34typedef struct DEBUGAUDIOSTREAM
35{
36 /** The stream's acquired configuration. */
37 PPDMAUDIOSTREAMCFG pCfg;
38 /** Audio file to dump output to or read input from. */
39 PPDMAUDIOFILE pFile;
40 union
41 {
42 struct
43 {
44 /** Timestamp of last captured samples. */
45 uint64_t tsLastCaptured;
46 } In;
47 };
48} DEBUGAUDIOSTREAM, *PDEBUGAUDIOSTREAM;
49
50/**
51 * Debug audio driver instance data.
52 * @implements PDMIAUDIOCONNECTOR
53 */
54typedef struct DRVHOSTDEBUGAUDIO
55{
56 /** Pointer to the driver instance structure. */
57 PPDMDRVINS pDrvIns;
58 /** Pointer to host audio interface. */
59 PDMIHOSTAUDIO IHostAudio;
60} DRVHOSTDEBUGAUDIO, *PDRVHOSTDEBUGAUDIO;
61
62/*******************************************PDM_AUDIO_DRIVER******************************/
63
64
65/**
66 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
67 */
68static DECLCALLBACK(int) drvHostDebugAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
69{
70 RT_NOREF(pInterface);
71 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
72
73 RTStrPrintf2(pBackendCfg->szName, sizeof(pBackendCfg->szName), "Debug audio driver");
74
75 pBackendCfg->cbStreamOut = sizeof(DEBUGAUDIOSTREAM);
76 pBackendCfg->cbStreamIn = sizeof(DEBUGAUDIOSTREAM);
77
78 pBackendCfg->cMaxStreamsOut = 1; /* Output; writing to a file. */
79 pBackendCfg->cMaxStreamsIn = 0; /** @todo Right now we don't support any input (capturing, injecting from a file). */
80
81 return VINF_SUCCESS;
82}
83
84
85/**
86 * @interface_method_impl{PDMIHOSTAUDIO,pfnInit}
87 */
88static DECLCALLBACK(int) drvHostDebugAudioInit(PPDMIHOSTAUDIO pInterface)
89{
90 RT_NOREF(pInterface);
91
92 LogFlowFuncLeaveRC(VINF_SUCCESS);
93 return VINF_SUCCESS;
94}
95
96
97/**
98 * @interface_method_impl{PDMIHOSTAUDIO,pfnShutdown}
99 */
100static DECLCALLBACK(void) drvHostDebugAudioShutdown(PPDMIHOSTAUDIO pInterface)
101{
102 RT_NOREF(pInterface);
103}
104
105
106/**
107 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
108 */
109static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostDebugAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
110{
111 RT_NOREF(enmDir);
112 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
113
114 return PDMAUDIOBACKENDSTS_RUNNING;
115}
116
117
118static int debugCreateStreamIn(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
119 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
120{
121 RT_NOREF(pDrv, pStreamDbg, pCfgReq, pCfgAcq);
122
123 return VINF_SUCCESS;
124}
125
126
127static int debugCreateStreamOut(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg,
128 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
129{
130 RT_NOREF(pDrv, pCfgAcq);
131
132 char szTemp[RTPATH_MAX];
133 int rc = RTPathTemp(szTemp, sizeof(szTemp));
134 if (RT_SUCCESS(rc))
135 {
136 char szFile[RTPATH_MAX];
137 rc = DrvAudioHlpFileNameGet(szFile, RT_ELEMENTS(szFile), szTemp, "DebugAudioOut",
138 pDrv->pDrvIns->iInstance, PDMAUDIOFILETYPE_WAV, PDMAUDIOFILENAME_FLAG_NONE);
139 if (RT_SUCCESS(rc))
140 {
141 rc = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE, &pStreamDbg->pFile);
142 if (RT_SUCCESS(rc))
143 {
144 rc = DrvAudioHlpFileOpen(pStreamDbg->pFile, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
145 &pCfgReq->Props);
146 }
147
148 if (RT_FAILURE(rc))
149 LogRel(("DebugAudio: Creating output file '%s' failed with %Rrc\n", szFile, rc));
150 }
151 else
152 LogRel(("DebugAudio: Unable to build file name for temp dir '%s': %Rrc\n", szTemp, rc));
153 }
154 else
155 LogRel(("DebugAudio: Unable to retrieve temp dir: %Rrc\n", rc));
156
157 return rc;
158}
159
160
161/**
162 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
163 */
164static DECLCALLBACK(int) drvHostDebugAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
165 PPDMAUDIOBACKENDSTREAM pStream,
166 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
167{
168 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
169 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
170 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
171 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
172
173 PDRVHOSTDEBUGAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTDEBUGAUDIO, IHostAudio);
174 PDEBUGAUDIOSTREAM pStreamDbg = (PDEBUGAUDIOSTREAM)pStream;
175
176 int rc;
177 if (pCfgReq->enmDir == PDMAUDIODIR_IN)
178 rc = debugCreateStreamIn( pDrv, pStreamDbg, pCfgReq, pCfgAcq);
179 else
180 rc = debugCreateStreamOut(pDrv, pStreamDbg, pCfgReq, pCfgAcq);
181
182 if (RT_SUCCESS(rc))
183 {
184 pStreamDbg->pCfg = DrvAudioHlpStreamCfgDup(pCfgAcq);
185 if (!pStreamDbg->pCfg)
186 rc = VERR_NO_MEMORY;
187 }
188
189 return rc;
190}
191
192
193/**
194 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
195 */
196static DECLCALLBACK(int) drvHostDebugAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
197 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
198{
199 RT_NOREF(pInterface);
200 PDEBUGAUDIOSTREAM pStreamDbg = (PDEBUGAUDIOSTREAM)pStream;
201
202 int rc = DrvAudioHlpFileWrite(pStreamDbg->pFile, pvBuf, uBufSize, 0 /* fFlags */);
203 if (RT_FAILURE(rc))
204 {
205 LogRel(("DebugAudio: Writing output failed with %Rrc\n", rc));
206 return rc;
207 }
208
209 if (puWritten)
210 *puWritten = uBufSize;
211
212 return VINF_SUCCESS;
213}
214
215
216/**
217 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
218 */
219static DECLCALLBACK(int) drvHostDebugAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
220 void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
221{
222 RT_NOREF(pInterface, pStream, pvBuf, uBufSize);
223
224 /* Never capture anything. */
225 if (puRead)
226 *puRead = 0;
227
228 return VINF_SUCCESS;
229}
230
231
232static int debugDestroyStreamIn(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg)
233{
234 RT_NOREF(pDrv, pStreamDbg);
235 return VINF_SUCCESS;
236}
237
238
239static int debugDestroyStreamOut(PDRVHOSTDEBUGAUDIO pDrv, PDEBUGAUDIOSTREAM pStreamDbg)
240{
241 RT_NOREF(pDrv);
242
243 DrvAudioHlpFileDestroy(pStreamDbg->pFile);
244
245 return VINF_SUCCESS;
246}
247
248
249/**
250 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
251 */
252static DECLCALLBACK(int) drvHostDebugAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
253{
254 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
255
256 PDRVHOSTDEBUGAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTDEBUGAUDIO, IHostAudio);
257 PDEBUGAUDIOSTREAM pStreamDbg = (PDEBUGAUDIOSTREAM)pStream;
258
259 if (!pStreamDbg->pCfg) /* Not (yet) configured? Skip. */
260 return VINF_SUCCESS;
261
262 int rc;
263 if (pStreamDbg->pCfg->enmDir == PDMAUDIODIR_IN)
264 rc = debugDestroyStreamIn (pDrv, pStreamDbg);
265 else
266 rc = debugDestroyStreamOut(pDrv, pStreamDbg);
267
268 if (RT_SUCCESS(rc))
269 {
270 DrvAudioHlpStreamCfgFree(pStreamDbg->pCfg);
271 pStreamDbg->pCfg = NULL;
272 }
273
274 return rc;
275}
276
277
278/**
279 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
280 */
281static DECLCALLBACK(int) drvHostDebugAudioStreamControl(PPDMIHOSTAUDIO pInterface,
282 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
283{
284 RT_NOREF(enmStreamCmd);
285 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
286 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
287
288 return VINF_SUCCESS;
289}
290
291
292/**
293 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
294 */
295static DECLCALLBACK(uint32_t) drvHostDebugAudioStreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
296{
297 RT_NOREF(pInterface, pStream);
298
299 return 0; /* Never capture anything. */
300}
301
302
303/**
304 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
305 */
306static DECLCALLBACK(uint32_t) drvHostDebugAudioStreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
307{
308 RT_NOREF(pInterface, pStream);
309
310 return UINT32_MAX;
311}
312
313
314/**
315 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
316 */
317static DECLCALLBACK(PDMAUDIOSTREAMSTS) drvHostDebugAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
318{
319 RT_NOREF(pInterface, pStream);
320
321 return (PDMAUDIOSTREAMSTS_FLAG_INITIALIZED | PDMAUDIOSTREAMSTS_FLAG_ENABLED);
322}
323
324
325/**
326 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
327 */
328static DECLCALLBACK(int) drvHostDebugAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
329{
330 RT_NOREF(pInterface, pStream);
331 return VINF_SUCCESS;
332}
333
334
335/**
336 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
337 */
338static DECLCALLBACK(void *) drvHostDebugAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
339{
340 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
341 PDRVHOSTDEBUGAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTDEBUGAUDIO);
342
343 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
344 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
345 return NULL;
346}
347
348
349/**
350 * Constructs a Null audio driver instance.
351 *
352 * @copydoc FNPDMDRVCONSTRUCT
353 */
354static DECLCALLBACK(int) drvHostDebugAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
355{
356 RT_NOREF(pCfg, fFlags);
357 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
358 PDRVHOSTDEBUGAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTDEBUGAUDIO);
359 LogRel(("Audio: Initializing DEBUG driver\n"));
360
361 /*
362 * Init the static parts.
363 */
364 pThis->pDrvIns = pDrvIns;
365 /* IBase */
366 pDrvIns->IBase.pfnQueryInterface = drvHostDebugAudioQueryInterface;
367 /* IHostAudio */
368 PDMAUDIO_IHOSTAUDIO_CALLBACKS(drvHostDebugAudio);
369
370#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
371 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "AudioDebugOutput.pcm");
372#endif
373
374 return VINF_SUCCESS;
375}
376
377/**
378 * Char driver registration record.
379 */
380const PDMDRVREG g_DrvHostDebugAudio =
381{
382 /* u32Version */
383 PDM_DRVREG_VERSION,
384 /* szName */
385 "DebugAudio",
386 /* szRCMod */
387 "",
388 /* szR0Mod */
389 "",
390 /* pszDescription */
391 "Debug audio host driver",
392 /* fFlags */
393 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
394 /* fClass. */
395 PDM_DRVREG_CLASS_AUDIO,
396 /* cMaxInstances */
397 ~0U,
398 /* cbInstance */
399 sizeof(DRVHOSTDEBUGAUDIO),
400 /* pfnConstruct */
401 drvHostDebugAudioConstruct,
402 /* pfnDestruct */
403 NULL,
404 /* pfnRelocate */
405 NULL,
406 /* pfnIOCtl */
407 NULL,
408 /* pfnPowerOn */
409 NULL,
410 /* pfnReset */
411 NULL,
412 /* pfnSuspend */
413 NULL,
414 /* pfnResume */
415 NULL,
416 /* pfnAttach */
417 NULL,
418 /* pfnDetach */
419 NULL,
420 /* pfnPowerOff */
421 NULL,
422 /* pfnSoftReset */
423 NULL,
424 /* u32EndVersion */
425 PDM_DRVREG_VERSION
426};
427
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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