VirtualBox

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

Last change on this file since 90778 was 90012, checked in by vboxsync, 3 years ago

Audio: Output multichannel capable wave files. Simplify the code a little, removing AudioHlpFileGetDataSize among other things. Dropped the unused flags parameter for AudioHlpFileWrite. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: DrvHostAudioDebug.cpp 90012 2021-07-04 21:08:37Z 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 pThis->pDrvIns->iInstance, AUDIOHLPFILENAME_FLAGS_NONE, AUDIOHLPFILE_FLAGS_NONE,
121 &pCfgReq->Props, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
122 pCfgReq->enmDir == PDMAUDIODIR_IN ? "DebugAudioIn" : "DebugAudioOut");
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_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
155{
156 RT_NOREF(pInterface, pStream);
157 return VINF_SUCCESS;
158}
159
160
161/**
162 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDisable}
163 */
164static DECLCALLBACK(int) drvHstAudDebugHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
165{
166 RT_NOREF(pInterface, pStream);
167 return VINF_SUCCESS;
168}
169
170
171/**
172 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPause}
173 */
174static DECLCALLBACK(int) drvHstAudDebugHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
175{
176 RT_NOREF(pInterface, pStream);
177 return VINF_SUCCESS;
178}
179
180
181/**
182 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamResume}
183 */
184static DECLCALLBACK(int) drvHstAudDebugHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
185{
186 RT_NOREF(pInterface, pStream);
187 return VINF_SUCCESS;
188}
189
190
191/**
192 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain}
193 */
194static DECLCALLBACK(int) drvHstAudDebugHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
195{
196 RT_NOREF(pInterface, pStream);
197 return VINF_SUCCESS;
198}
199
200
201/**
202 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetState}
203 */
204static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvHstAudDebugHA_StreamGetState(PPDMIHOSTAUDIO pInterface,
205 PPDMAUDIOBACKENDSTREAM pStream)
206{
207 RT_NOREF(pInterface);
208 AssertPtrReturn(pStream, PDMHOSTAUDIOSTREAMSTATE_INVALID);
209 return PDMHOSTAUDIOSTREAMSTATE_OKAY;
210}
211
212
213/**
214 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetPending}
215 */
216static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
217{
218 RT_NOREF(pInterface, pStream);
219 return 0;
220}
221
222
223/**
224 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
225 */
226static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
227{
228 RT_NOREF(pInterface, pStream);
229 return UINT32_MAX;
230}
231
232
233/**
234 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
235 */
236static DECLCALLBACK(int) drvHstAudDebugHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
237 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
238{
239 RT_NOREF(pInterface);
240 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
241
242 int rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbBuf);
243 if (RT_SUCCESS(rc))
244 *pcbWritten = cbBuf;
245 else
246 LogRelMax(32, ("DebugAudio: Writing output failed with %Rrc\n", rc));
247 return rc;
248}
249
250
251/**
252 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
253 */
254static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
255{
256 RT_NOREF(pInterface);
257 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
258
259 return PDMAudioPropsMilliToBytes(&pStreamDbg->Cfg.Props, 10 /*ms*/);
260}
261
262
263/**
264 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
265 */
266static DECLCALLBACK(int) drvHstAudDebugHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
267 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
268{
269 RT_NOREF(pInterface);
270 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
271/** @todo rate limit this? */
272
273 uint32_t cbWritten;
274 int rc = AudioTestToneGenerate(&pStreamDbg->In, pvBuf, cbBuf, &cbWritten);
275 if (RT_SUCCESS(rc))
276 {
277 /*
278 * Write it.
279 */
280 rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbWritten);
281 if (RT_SUCCESS(rc))
282 *pcbRead = cbWritten;
283 }
284
285 if (RT_FAILURE(rc))
286 LogRelMax(32, ("DebugAudio: Writing input failed with %Rrc\n", rc));
287
288 return rc;
289}
290
291
292/**
293 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
294 */
295static DECLCALLBACK(void *) drvHstAudDebugQueryInterface(PPDMIBASE pInterface, const char *pszIID)
296{
297 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
298 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
299
300 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
301 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
302 return NULL;
303}
304
305
306/**
307 * Constructs a Null audio driver instance.
308 *
309 * @copydoc FNPDMDRVCONSTRUCT
310 */
311static DECLCALLBACK(int) drvHstAudDebugConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
312{
313 RT_NOREF(pCfg, fFlags);
314 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
315 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
316 LogRel(("Audio: Initializing DEBUG driver\n"));
317
318 /*
319 * Init the static parts.
320 */
321 pThis->pDrvIns = pDrvIns;
322 /* IBase */
323 pDrvIns->IBase.pfnQueryInterface = drvHstAudDebugQueryInterface;
324 /* IHostAudio */
325 pThis->IHostAudio.pfnGetConfig = drvHstAudDebugHA_GetConfig;
326 pThis->IHostAudio.pfnGetDevices = NULL;
327 pThis->IHostAudio.pfnSetDevice = NULL;
328 pThis->IHostAudio.pfnGetStatus = drvHstAudDebugHA_GetStatus;
329 pThis->IHostAudio.pfnDoOnWorkerThread = NULL;
330 pThis->IHostAudio.pfnStreamConfigHint = NULL;
331 pThis->IHostAudio.pfnStreamCreate = drvHstAudDebugHA_StreamCreate;
332 pThis->IHostAudio.pfnStreamInitAsync = NULL;
333 pThis->IHostAudio.pfnStreamDestroy = drvHstAudDebugHA_StreamDestroy;
334 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = NULL;
335 pThis->IHostAudio.pfnStreamEnable = drvHstAudDebugHA_StreamEnable;
336 pThis->IHostAudio.pfnStreamDisable = drvHstAudDebugHA_StreamDisable;
337 pThis->IHostAudio.pfnStreamPause = drvHstAudDebugHA_StreamPause;
338 pThis->IHostAudio.pfnStreamResume = drvHstAudDebugHA_StreamResume;
339 pThis->IHostAudio.pfnStreamDrain = drvHstAudDebugHA_StreamDrain;
340 pThis->IHostAudio.pfnStreamGetState = drvHstAudDebugHA_StreamGetState;
341 pThis->IHostAudio.pfnStreamGetPending = drvHstAudDebugHA_StreamGetPending;
342 pThis->IHostAudio.pfnStreamGetWritable = drvHstAudDebugHA_StreamGetWritable;
343 pThis->IHostAudio.pfnStreamPlay = drvHstAudDebugHA_StreamPlay;
344 pThis->IHostAudio.pfnStreamGetReadable = drvHstAudDebugHA_StreamGetReadable;
345 pThis->IHostAudio.pfnStreamCapture = drvHstAudDebugHA_StreamCapture;
346
347#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH
348 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "AudioDebugOutput.pcm");
349#endif
350
351 return VINF_SUCCESS;
352}
353
354/**
355 * Char driver registration record.
356 */
357const PDMDRVREG g_DrvHostDebugAudio =
358{
359 /* u32Version */
360 PDM_DRVREG_VERSION,
361 /* szName */
362 "DebugAudio",
363 /* szRCMod */
364 "",
365 /* szR0Mod */
366 "",
367 /* pszDescription */
368 "Debug audio host driver",
369 /* fFlags */
370 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
371 /* fClass. */
372 PDM_DRVREG_CLASS_AUDIO,
373 /* cMaxInstances */
374 ~0U,
375 /* cbInstance */
376 sizeof(DRVHSTAUDDEBUG),
377 /* pfnConstruct */
378 drvHstAudDebugConstruct,
379 /* pfnDestruct */
380 NULL,
381 /* pfnRelocate */
382 NULL,
383 /* pfnIOCtl */
384 NULL,
385 /* pfnPowerOn */
386 NULL,
387 /* pfnReset */
388 NULL,
389 /* pfnSuspend */
390 NULL,
391 /* pfnResume */
392 NULL,
393 /* pfnAttach */
394 NULL,
395 /* pfnDetach */
396 NULL,
397 /* pfnPowerOff */
398 NULL,
399 /* pfnSoftReset */
400 NULL,
401 /* u32EndVersion */
402 PDM_DRVREG_VERSION
403};
404
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use