VirtualBox

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

Last change on this file since 103914 was 98103, checked in by vboxsync, 22 months ago

Copyright year updates by scm.

  • 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 98103 2023-01-17 14:15: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-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
33#include <VBox/log.h>
34#include <VBox/vmm/pdmaudioifs.h>
35#include <VBox/vmm/pdmaudioinline.h>
36
37#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
38
39#include "AudioHlp.h"
40#include "AudioTest.h"
41#include "VBoxDD.h"
42
43
44/*********************************************************************************************************************************
45* Structures and Typedefs *
46*********************************************************************************************************************************/
47/**
48 * Debug host audio stream.
49 */
50typedef struct DRVHSTAUDDEBUGSTREAM
51{
52 /** Common part. */
53 PDMAUDIOBACKENDSTREAM Core;
54 /** The stream's acquired configuration. */
55 PDMAUDIOSTREAMCFG Cfg;
56 /** Audio file to dump output to or read input from. */
57 PAUDIOHLPFILE pFile;
58 union
59 {
60 AUDIOTESTTONE In;
61 };
62} DRVHSTAUDDEBUGSTREAM;
63/** Pointer to a debug host audio stream. */
64typedef DRVHSTAUDDEBUGSTREAM *PDRVHSTAUDDEBUGSTREAM;
65
66/**
67 * Debug audio driver instance data.
68 * @implements PDMIAUDIOCONNECTOR
69 */
70typedef struct DRVHSTAUDDEBUG
71{
72 /** Pointer to the driver instance structure. */
73 PPDMDRVINS pDrvIns;
74 /** Pointer to host audio interface. */
75 PDMIHOSTAUDIO IHostAudio;
76} DRVHSTAUDDEBUG;
77/** Pointer to a debug host audio driver. */
78typedef DRVHSTAUDDEBUG *PDRVHSTAUDDEBUG;
79
80
81/**
82 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
83 */
84static DECLCALLBACK(int) drvHstAudDebugHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
85{
86 RT_NOREF(pInterface);
87 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
88
89 /*
90 * Fill in the config structure.
91 */
92 RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "DebugAudio");
93 pBackendCfg->cbStream = sizeof(DRVHSTAUDDEBUGSTREAM);
94 pBackendCfg->fFlags = 0;
95 pBackendCfg->cMaxStreamsOut = 1; /* Output; writing to a file. */
96 pBackendCfg->cMaxStreamsIn = 1; /* Input; generates a sine wave. */
97
98 return VINF_SUCCESS;
99}
100
101
102/**
103 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
104 */
105static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHstAudDebugHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
106{
107 RT_NOREF(pInterface, enmDir);
108 return PDMAUDIOBACKENDSTS_RUNNING;
109}
110
111
112/**
113 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
114 */
115static DECLCALLBACK(int) drvHstAudDebugHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
116 PCPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
117{
118 PDRVHSTAUDDEBUG pThis = RT_FROM_MEMBER(pInterface, DRVHSTAUDDEBUG, IHostAudio);
119 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
120 AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
121 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
122 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
123
124 PDMAudioStrmCfgCopy(&pStreamDbg->Cfg, pCfgAcq);
125
126 if (pCfgReq->enmDir == PDMAUDIODIR_IN)
127 AudioTestToneInitRandom(&pStreamDbg->In, &pStreamDbg->Cfg.Props);
128
129 int rc = AudioHlpFileCreateAndOpenEx(&pStreamDbg->pFile, AUDIOHLPFILETYPE_WAV, NULL /*use temp dir*/,
130 pThis->pDrvIns->iInstance, AUDIOHLPFILENAME_FLAGS_NONE, AUDIOHLPFILE_FLAGS_NONE,
131 &pCfgReq->Props, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE,
132 pCfgReq->enmDir == PDMAUDIODIR_IN ? "DebugAudioIn" : "DebugAudioOut");
133 if (RT_FAILURE(rc))
134 LogRel(("DebugAudio: Failed to creating debug file for %s stream '%s' in the temp directory: %Rrc\n",
135 pCfgReq->enmDir == PDMAUDIODIR_IN ? "input" : "output", pCfgReq->szName, rc));
136
137 return rc;
138}
139
140
141/**
142 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
143 */
144static DECLCALLBACK(int) drvHstAudDebugHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
145 bool fImmediate)
146{
147 RT_NOREF(pInterface, fImmediate);
148 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
149 AssertPtrReturn(pStreamDbg, VERR_INVALID_POINTER);
150
151 if (pStreamDbg->pFile)
152 {
153 AudioHlpFileDestroy(pStreamDbg->pFile);
154 pStreamDbg->pFile = NULL;
155 }
156
157 return VINF_SUCCESS;
158}
159
160
161/**
162 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable}
163 */
164static DECLCALLBACK(int) drvHstAudDebugHA_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
165{
166 RT_NOREF(pInterface, pStream);
167 return VINF_SUCCESS;
168}
169
170
171/**
172 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDisable}
173 */
174static DECLCALLBACK(int) drvHstAudDebugHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
175{
176 RT_NOREF(pInterface, pStream);
177 return VINF_SUCCESS;
178}
179
180
181/**
182 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPause}
183 */
184static DECLCALLBACK(int) drvHstAudDebugHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
185{
186 RT_NOREF(pInterface, pStream);
187 return VINF_SUCCESS;
188}
189
190
191/**
192 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamResume}
193 */
194static DECLCALLBACK(int) drvHstAudDebugHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
195{
196 RT_NOREF(pInterface, pStream);
197 return VINF_SUCCESS;
198}
199
200
201/**
202 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain}
203 */
204static DECLCALLBACK(int) drvHstAudDebugHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
205{
206 RT_NOREF(pInterface, pStream);
207 return VINF_SUCCESS;
208}
209
210
211/**
212 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetState}
213 */
214static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvHstAudDebugHA_StreamGetState(PPDMIHOSTAUDIO pInterface,
215 PPDMAUDIOBACKENDSTREAM pStream)
216{
217 RT_NOREF(pInterface);
218 AssertPtrReturn(pStream, PDMHOSTAUDIOSTREAMSTATE_INVALID);
219 return PDMHOSTAUDIOSTREAMSTATE_OKAY;
220}
221
222
223/**
224 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetPending}
225 */
226static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
227{
228 RT_NOREF(pInterface, pStream);
229 return 0;
230}
231
232
233/**
234 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
235 */
236static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
237{
238 RT_NOREF(pInterface, pStream);
239 return UINT32_MAX;
240}
241
242
243/**
244 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
245 */
246static DECLCALLBACK(int) drvHstAudDebugHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
247 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
248{
249 RT_NOREF(pInterface);
250 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
251
252 int rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbBuf);
253 if (RT_SUCCESS(rc))
254 *pcbWritten = cbBuf;
255 else
256 LogRelMax(32, ("DebugAudio: Writing output failed with %Rrc\n", rc));
257 return rc;
258}
259
260
261/**
262 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
263 */
264static DECLCALLBACK(uint32_t) drvHstAudDebugHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
265{
266 RT_NOREF(pInterface);
267 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
268
269 return PDMAudioPropsMilliToBytes(&pStreamDbg->Cfg.Props, 10 /*ms*/);
270}
271
272
273/**
274 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
275 */
276static DECLCALLBACK(int) drvHstAudDebugHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
277 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
278{
279 RT_NOREF(pInterface);
280 PDRVHSTAUDDEBUGSTREAM pStreamDbg = (PDRVHSTAUDDEBUGSTREAM)pStream;
281/** @todo rate limit this? */
282
283 uint32_t cbWritten;
284 int rc = AudioTestToneGenerate(&pStreamDbg->In, pvBuf, cbBuf, &cbWritten);
285 if (RT_SUCCESS(rc))
286 {
287 /*
288 * Write it.
289 */
290 rc = AudioHlpFileWrite(pStreamDbg->pFile, pvBuf, cbWritten);
291 if (RT_SUCCESS(rc))
292 *pcbRead = cbWritten;
293 }
294
295 if (RT_FAILURE(rc))
296 LogRelMax(32, ("DebugAudio: Writing input failed with %Rrc\n", rc));
297
298 return rc;
299}
300
301
302/**
303 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
304 */
305static DECLCALLBACK(void *) drvHstAudDebugQueryInterface(PPDMIBASE pInterface, const char *pszIID)
306{
307 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
308 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
309
310 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
311 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
312 return NULL;
313}
314
315
316/**
317 * Constructs a Null audio driver instance.
318 *
319 * @copydoc FNPDMDRVCONSTRUCT
320 */
321static DECLCALLBACK(int) drvHstAudDebugConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
322{
323 RT_NOREF(pCfg, fFlags);
324 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
325 PDRVHSTAUDDEBUG pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDDEBUG);
326 LogRel(("Audio: Initializing DEBUG driver\n"));
327
328 /*
329 * Init the static parts.
330 */
331 pThis->pDrvIns = pDrvIns;
332 /* IBase */
333 pDrvIns->IBase.pfnQueryInterface = drvHstAudDebugQueryInterface;
334 /* IHostAudio */
335 pThis->IHostAudio.pfnGetConfig = drvHstAudDebugHA_GetConfig;
336 pThis->IHostAudio.pfnGetDevices = NULL;
337 pThis->IHostAudio.pfnSetDevice = NULL;
338 pThis->IHostAudio.pfnGetStatus = drvHstAudDebugHA_GetStatus;
339 pThis->IHostAudio.pfnDoOnWorkerThread = NULL;
340 pThis->IHostAudio.pfnStreamConfigHint = NULL;
341 pThis->IHostAudio.pfnStreamCreate = drvHstAudDebugHA_StreamCreate;
342 pThis->IHostAudio.pfnStreamInitAsync = NULL;
343 pThis->IHostAudio.pfnStreamDestroy = drvHstAudDebugHA_StreamDestroy;
344 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = NULL;
345 pThis->IHostAudio.pfnStreamEnable = drvHstAudDebugHA_StreamEnable;
346 pThis->IHostAudio.pfnStreamDisable = drvHstAudDebugHA_StreamDisable;
347 pThis->IHostAudio.pfnStreamPause = drvHstAudDebugHA_StreamPause;
348 pThis->IHostAudio.pfnStreamResume = drvHstAudDebugHA_StreamResume;
349 pThis->IHostAudio.pfnStreamDrain = drvHstAudDebugHA_StreamDrain;
350 pThis->IHostAudio.pfnStreamGetState = drvHstAudDebugHA_StreamGetState;
351 pThis->IHostAudio.pfnStreamGetPending = drvHstAudDebugHA_StreamGetPending;
352 pThis->IHostAudio.pfnStreamGetWritable = drvHstAudDebugHA_StreamGetWritable;
353 pThis->IHostAudio.pfnStreamPlay = drvHstAudDebugHA_StreamPlay;
354 pThis->IHostAudio.pfnStreamGetReadable = drvHstAudDebugHA_StreamGetReadable;
355 pThis->IHostAudio.pfnStreamCapture = drvHstAudDebugHA_StreamCapture;
356
357 return VINF_SUCCESS;
358}
359
360/**
361 * Char driver registration record.
362 */
363const PDMDRVREG g_DrvHostDebugAudio =
364{
365 /* u32Version */
366 PDM_DRVREG_VERSION,
367 /* szName */
368 "DebugAudio",
369 /* szRCMod */
370 "",
371 /* szR0Mod */
372 "",
373 /* pszDescription */
374 "Debug audio host driver",
375 /* fFlags */
376 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
377 /* fClass. */
378 PDM_DRVREG_CLASS_AUDIO,
379 /* cMaxInstances */
380 ~0U,
381 /* cbInstance */
382 sizeof(DRVHSTAUDDEBUG),
383 /* pfnConstruct */
384 drvHstAudDebugConstruct,
385 /* pfnDestruct */
386 NULL,
387 /* pfnRelocate */
388 NULL,
389 /* pfnIOCtl */
390 NULL,
391 /* pfnPowerOn */
392 NULL,
393 /* pfnReset */
394 NULL,
395 /* pfnSuspend */
396 NULL,
397 /* pfnResume */
398 NULL,
399 /* pfnAttach */
400 NULL,
401 /* pfnDetach */
402 NULL,
403 /* pfnPowerOff */
404 NULL,
405 /* pfnSoftReset */
406 NULL,
407 /* u32EndVersion */
408 PDM_DRVREG_VERSION
409};
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