VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostAudioDebug.cpp@ 89504

Last change on this file since 89504 was 89504, checked in by vboxsync, 4 years ago

Audio: Re-ordering some methods, no real change. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1/* $Id: DrvHostAudioDebug.cpp 89504 2021-06-04 11:30:46Z vboxsync $ */
2/** @file
3 * Host audio driver - Debug - For dumping and injecting audio data from/to the device emulation.
4 */
5
6/*
7 * Copyright (C) 2016-2021 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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
23#include <VBox/log.h>
24#include <VBox/vmm/pdmaudioifs.h>
25#include <VBox/vmm/pdmaudioinline.h>
26
27#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
28
29#include "AudioHlp.h"
30#include "AudioTest.h"
31#include "VBoxDD.h"
32
33
34/*********************************************************************************************************************************
35* Structures and Typedefs *
36*********************************************************************************************************************************/
37/**
38 * Debug host audio stream.
39 */
40typedef struct DRVHSTAUDDEBUGSTREAM
41{
42 /** Common part. */
43 PDMAUDIOBACKENDSTREAM Core;
44 /** The stream's acquired configuration. */
45 PDMAUDIOSTREAMCFG Cfg;
46 /** Audio file to dump output to or read input from. */
47 PAUDIOHLPFILE pFile;
48 union
49 {
50 AUDIOTESTTONE In;
51 };
52} DRVHSTAUDDEBUGSTREAM;
53/** Pointer to a debug host audio stream. */
54typedef DRVHSTAUDDEBUGSTREAM *PDRVHSTAUDDEBUGSTREAM;
55
56/**
57 * Debug audio driver instance data.
58 * @implements PDMIAUDIOCONNECTOR
59 */
60typedef struct DRVHSTAUDDEBUG
61{
62 /** Pointer to the driver instance structure. */
63 PPDMDRVINS pDrvIns;
64 /** Pointer to host audio interface. */
65 PDMIHOSTAUDIO IHostAudio;
66} DRVHSTAUDDEBUG;
67/** Pointer to a debug host audio driver. */
68typedef DRVHSTAUDDEBUG *PDRVHSTAUDDEBUG;
69
70
71/**
72 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
73 */
74static DECLCALLBACK(int) drvHstAudDebugHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
75{
76 RT_NOREF(pInterface);
77 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
78
79 /*
80 * Fill in the config structure.
81 */
82 RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "DebugAudio");
83 pBackendCfg->cbStream = sizeof(DRVHSTAUDDEBUGSTREAM);
84 pBackendCfg->fFlags = 0;
85 pBackendCfg->cMaxStreamsOut = 1; /* Output; writing to a file. */
86 pBackendCfg->cMaxStreamsIn = 1; /* Input; generates a sine wave. */
87
88 return VINF_SUCCESS;
89}
90
91
92/**
93 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
94 */
95static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHstAudDebugHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
96{
97 RT_NOREF(pInterface, enmDir);
98 return PDMAUDIOBACKENDSTS_RUNNING;
99}
100
101
102/**
103 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
104 */
105static DECLCALLBACK(int) drvHstAudDebugHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
106 PCPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
107{
108 PDRVHSTAUDDEBUG pThis = RT_FROM_MEMBER(pInterface, DRVHSTAUDDEBUG, IHostAudio);
109 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
110 AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
111 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
112 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
113
114 PDMAudioStrmCfgCopy(&pStreamDbg->Cfg, pCfgAcq);
115
116 if (pCfgReq->enmDir == PDMAUDIODIR_IN)
117 AudioTestToneInitRandom(&pStreamDbg->In, &pStreamDbg->Cfg.Props);
118
119 int rc = AudioHlpFileCreateAndOpenEx(&pStreamDbg->pFile, AUDIOHLPFILETYPE_WAV, NULL /*use temp dir*/,
120 pCfgReq->enmDir == PDMAUDIODIR_IN ? "DebugAudioIn" : "DebugAudioOut",
121 pThis->pDrvIns->iInstance, AUDIOHLPFILENAME_FLAGS_NONE, AUDIOHLPFILE_FLAGS_NONE,
122 &pCfgReq->Props, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE);
123 if (RT_FAILURE(rc))
124 LogRel(("DebugAudio: Failed to creating debug file for %s stream '%s' in the temp directory: %Rrc\n",
125 pCfgReq->enmDir == PDMAUDIODIR_IN ? "input" : "output", pCfgReq->szName, rc));
126
127 return rc;
128}
129
130
131/**
132 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
133 */
134static DECLCALLBACK(int) drvHstAudDebugHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
135 bool fImmediate)
136{
137 RT_NOREF(pInterface, fImmediate);
138 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
139 AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
140
141 if (pStreamDbg->pFile)
142 {
143 AudioHlpFileDestroy(pStreamDbg->pFile);
144 pStreamDbg->pFile = NULL;
145 }
146
147 return VINF_SUCCESS;
148}
149
150
151/**
152 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable}
153 */
154static DECLCALLBACK(int) drvHstAudDebugHA_StreamControlStub(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
155{
156 RT_NOREF(pInterface, pStream);
157 return VINF_SUCCESS;
158}
159
160
161/**
162 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
163 */
164static DECLCALLBACK(int) drvHstAudDebugHA_StreamControl(PPDMIHOSTAUDIO pInterface,
165 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
166{
167 /** @todo r=bird: I'd like to get rid of this pfnStreamControl method,
168 * replacing it with individual StreamXxxx methods. That would save us
169 * potentally huge switches and more easily see which drivers implement
170 * which operations (grep for pfnStreamXxxx). */
171 switch (enmStreamCmd)
172 {
173 case PDMAUDIOSTREAMCMD_ENABLE:
174 return drvHstAudDebugHA_StreamControlStub(pInterface, pStream);
175 case PDMAUDIOSTREAMCMD_DISABLE:
176 return drvHstAudDebugHA_StreamControlStub(pInterface, pStream);
177 case PDMAUDIOSTREAMCMD_PAUSE:
178 return drvHstAudDebugHA_StreamControlStub(pInterface, pStream);
179 case PDMAUDIOSTREAMCMD_RESUME:
180 return drvHstAudDebugHA_StreamControlStub(pInterface, pStream);
181 case PDMAUDIOSTREAMCMD_DRAIN:
182 return drvHstAudDebugHA_StreamControlStub(pInterface, pStream);
183
184 case PDMAUDIOSTREAMCMD_END:
185 case PDMAUDIOSTREAMCMD_32BIT_HACK:
186 case PDMAUDIOSTREAMCMD_INVALID:
187 /* no default*/
188 break;
189 }
190 return VERR_NOT_SUPPORTED;
191}
192
193
194/**
195 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetState}
196 */
197static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvHstAudDebugHA_StreamGetState(PPDMIHOSTAUDIO pInterface,
198 PPDMAUDIOBACKENDSTREAM pStream)
199{
200 RT_NOREF(pInterface);
201 AssertPtrReturn(pStream, PDMHOSTAUDIOSTREAMSTATE_INVALID);
202 return PDMHOSTAUDIOSTREAMSTATE_OKAY;
203}
204
205
206/**
207 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetPending}
208 */
209static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
210{
211 RT_NOREF(pInterface, pStream);
212 return 0;
213}
214
215
216/**
217 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
218 */
219static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
220{
221 RT_NOREF(pInterface, pStream);
222 return UINT32_MAX;
223}
224
225
226/**
227 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
228 */
229static DECLCALLBACK(int) drvHstAudDebugHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
230 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
231{
232 RT_NOREF(pInterface);
233 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
234
235 int rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbBuf, 0 /* fFlags */);
236 if (RT_SUCCESS(rc))
237 *pcbWritten = cbBuf;
238 else
239 LogRelMax(32, ("DebugAudio: Writing output failed with %Rrc\n", rc));
240 return rc;
241}
242
243
244/**
245 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
246 */
247static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
248{
249 RT_NOREF(pInterface);
250 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
251
252 return PDMAudioPropsMilliToBytes(&pStreamDbg->Cfg.Props, 10 /*ms*/);
253}
254
255
256/**
257 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
258 */
259static DECLCALLBACK(int) drvHstAudDebugHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
260 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
261{
262 RT_NOREF(pInterface);
263 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
264/** @todo rate limit this? */
265
266 uint32_t cbWritten;
267 int rc = AudioTestToneGenerate(&pStreamDbg->In, pvBuf, cbBuf, &cbWritten);
268 if (RT_SUCCESS(rc))
269 {
270 /*
271 * Write it.
272 */
273 rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbWritten, 0 /* fFlags */);
274 if (RT_SUCCESS(rc))
275 *pcbRead = cbWritten;
276 }
277
278 if (RT_FAILURE(rc))
279 LogRelMax(32, ("DebugAudio: Writing input failed with %Rrc\n", rc));
280
281 return rc;
282}
283
284
285/**
286 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
287 */
288static DECLCALLBACK(void *) drvHstAudDebugQueryInterface(PPDMIBASE pInterface, const char *pszIID)
289{
290 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
291 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
292
293 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
294 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
295 return NULL;
296}
297
298
299/**
300 * Constructs a Null audio driver instance.
301 *
302 * @copydoc FNPDMDRVCONSTRUCT
303 */
304static DECLCALLBACK(int) drvHstAudDebugConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
305{
306 RT_NOREF(pCfg, fFlags);
307 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
308 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
309 LogRel(("Audio: Initializing DEBUG driver\n"));
310
311 /*
312 * Init the static parts.
313 */
314 pThis->pDrvIns = pDrvIns;
315 /* IBase */
316 pDrvIns->IBase.pfnQueryInterface = drvHstAudDebugQueryInterface;
317 /* IHostAudio */
318 pThis->IHostAudio.pfnGetConfig = drvHstAudDebugHA_GetConfig;
319 pThis->IHostAudio.pfnGetDevices = NULL;
320 pThis->IHostAudio.pfnSetDevice = NULL;
321 pThis->IHostAudio.pfnGetStatus = drvHstAudDebugHA_GetStatus;
322 pThis->IHostAudio.pfnDoOnWorkerThread = NULL;
323 pThis->IHostAudio.pfnStreamConfigHint = NULL;
324 pThis->IHostAudio.pfnStreamCreate = drvHstAudDebugHA_StreamCreate;
325 pThis->IHostAudio.pfnStreamInitAsync = NULL;
326 pThis->IHostAudio.pfnStreamDestroy = drvHstAudDebugHA_StreamDestroy;
327 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = NULL;
328 pThis->IHostAudio.pfnStreamControl = drvHstAudDebugHA_StreamControl;
329 pThis->IHostAudio.pfnStreamGetState = drvHstAudDebugHA_StreamGetState;
330 pThis->IHostAudio.pfnStreamGetPending = drvHstAudDebugHA_StreamGetPending;
331 pThis->IHostAudio.pfnStreamGetWritable = drvHstAudDebugHA_StreamGetWritable;
332 pThis->IHostAudio.pfnStreamPlay = drvHstAudDebugHA_StreamPlay;
333 pThis->IHostAudio.pfnStreamGetReadable = drvHstAudDebugHA_StreamGetReadable;
334 pThis->IHostAudio.pfnStreamCapture = drvHstAudDebugHA_StreamCapture;
335
336#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH
337 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "AudioDebugOutput.pcm");
338#endif
339
340 return VINF_SUCCESS;
341}
342
343/**
344 * Char driver registration record.
345 */
346const PDMDRVREG g_DrvHostDebugAudio =
347{
348 /* u32Version */
349 PDM_DRVREG_VERSION,
350 /* szName */
351 "DebugAudio",
352 /* szRCMod */
353 "",
354 /* szR0Mod */
355 "",
356 /* pszDescription */
357 "Debug audio host driver",
358 /* fFlags */
359 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
360 /* fClass. */
361 PDM_DRVREG_CLASS_AUDIO,
362 /* cMaxInstances */
363 ~0U,
364 /* cbInstance */
365 sizeof(DRVHSTAUDDEBUG),
366 /* pfnConstruct */
367 drvHstAudDebugConstruct,
368 /* pfnDestruct */
369 NULL,
370 /* pfnRelocate */
371 NULL,
372 /* pfnIOCtl */
373 NULL,
374 /* pfnPowerOn */
375 NULL,
376 /* pfnReset */
377 NULL,
378 /* pfnSuspend */
379 NULL,
380 /* pfnResume */
381 NULL,
382 /* pfnAttach */
383 NULL,
384 /* pfnDetach */
385 NULL,
386 /* pfnPowerOff */
387 NULL,
388 /* pfnSoftReset */
389 NULL,
390 /* u32EndVersion */
391 PDM_DRVREG_VERSION
392};
393
Note: See TracBrowser for help on using the repository browser.

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