VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp@ 88037

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

Audio: Moving some of the DrvAudio.h stuff into PDM - VBox/vmm/pdmaudioinline.h. 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: DrvHostNullAudio.cpp 88028 2021-03-08 19:31:22Z vboxsync $ */
2/** @file
3 * NULL audio driver.
4 *
5 * This also acts as a fallback if no other backend is available.
6 */
7
8/*
9 * Copyright (C) 2006-2020 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.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 * This code is based on: noaudio.c QEMU based code.
21 *
22 * QEMU Timer based audio emulation
23 *
24 * Copyright (c) 2004-2005 Vassili Karpov (malc)
25 *
26 * Permission is hereby granted, free of charge, to any person obtaining a copy
27 * of this software and associated documentation files (the "Software"), to deal
28 * in the Software without restriction, including without limitation the rights
29 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 * copies of the Software, and to permit persons to whom the Software is
31 * furnished to do so, subject to the following conditions:
32 *
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42 * THE SOFTWARE.
43 */
44
45
46/*********************************************************************************************************************************
47* Header Files *
48*********************************************************************************************************************************/
49#include <iprt/mem.h>
50#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
51
52#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
53#include <VBox/log.h>
54#include <VBox/vmm/pdmaudioifs.h>
55#include <VBox/vmm/pdmaudioinline.h>
56
57#include "DrvAudio.h"
58#include "VBoxDD.h"
59
60
61/*********************************************************************************************************************************
62* Structures and Typedefs *
63*********************************************************************************************************************************/
64typedef struct NULLAUDIOSTREAM
65{
66 /** The stream's acquired configuration. */
67 PPDMAUDIOSTREAMCFG pCfg;
68} NULLAUDIOSTREAM, *PNULLAUDIOSTREAM;
69
70/**
71 * NULL audio driver instance data.
72 * @implements PDMIAUDIOCONNECTOR
73 */
74typedef struct DRVHOSTNULLAUDIO
75{
76 /** Pointer to the driver instance structure. */
77 PPDMDRVINS pDrvIns;
78 /** Pointer to host audio interface. */
79 PDMIHOSTAUDIO IHostAudio;
80} DRVHOSTNULLAUDIO, *PDRVHOSTNULLAUDIO;
81
82
83
84/**
85 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
86 */
87static DECLCALLBACK(int) drvHostNullAudioHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
88{
89 NOREF(pInterface);
90 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
91
92 RTStrPrintf2(pBackendCfg->szName, sizeof(pBackendCfg->szName), "NULL audio");
93
94 pBackendCfg->cbStreamOut = sizeof(NULLAUDIOSTREAM);
95 pBackendCfg->cbStreamIn = sizeof(NULLAUDIOSTREAM);
96
97 pBackendCfg->cMaxStreamsOut = 1; /* Output */
98 pBackendCfg->cMaxStreamsIn = 2; /* Line input + microphone input. */
99
100 return VINF_SUCCESS;
101}
102
103
104/**
105 * @interface_method_impl{PDMIHOSTAUDIO,pfnInit}
106 */
107static DECLCALLBACK(int) drvHostNullAudioHA_Init(PPDMIHOSTAUDIO pInterface)
108{
109 NOREF(pInterface);
110
111 LogFlowFuncLeaveRC(VINF_SUCCESS);
112 return VINF_SUCCESS;
113}
114
115
116/**
117 * @interface_method_impl{PDMIHOSTAUDIO,pfnShutdown}
118 */
119static DECLCALLBACK(void) drvHostNullAudioHA_Shutdown(PPDMIHOSTAUDIO pInterface)
120{
121 RT_NOREF(pInterface);
122}
123
124
125/**
126 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
127 */
128static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostNullAudioHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
129{
130 RT_NOREF(enmDir);
131 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
132
133 return PDMAUDIOBACKENDSTS_RUNNING;
134}
135
136
137/**
138 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
139 */
140static DECLCALLBACK(int) drvHostNullAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
141 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten)
142{
143 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
144 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
145 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
146 AssertReturn(uBufSize, VERR_INVALID_PARAMETER);
147
148 RT_NOREF(pInterface, pStream, pvBuf);
149
150 /* Note: No copying of samples needed here, as this a NULL backend. */
151
152 if (puWritten)
153 *puWritten = uBufSize; /* Return all bytes as written. */
154
155 return VINF_SUCCESS;
156}
157
158
159/**
160 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
161 */
162static DECLCALLBACK(int) drvHostNullAudioHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
163 void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
164{
165 RT_NOREF(pInterface, pStream);
166
167 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
168
169 /* Return silence. */
170 Assert(pStreamNull->pCfg);
171 PDMAudioPropsClearBuffer(&pStreamNull->pCfg->Props, pvBuf, uBufSize, PDMAUDIOPCMPROPS_B2F(&pStreamNull->pCfg->Props, uBufSize));
172
173 if (puRead)
174 *puRead = uBufSize;
175
176 return VINF_SUCCESS;
177}
178
179
180static int nullCreateStreamIn(PNULLAUDIOSTREAM pStreamNull, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
181{
182 RT_NOREF(pStreamNull, pCfgReq, pCfgAcq);
183
184 return VINF_SUCCESS;
185}
186
187
188static int nullCreateStreamOut(PNULLAUDIOSTREAM pStreamNull, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
189{
190 RT_NOREF(pStreamNull, pCfgReq, pCfgAcq);
191
192 return VINF_SUCCESS;
193}
194
195
196/**
197 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
198 */
199static DECLCALLBACK(int) drvHostNullAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
200 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
201{
202 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
203 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
204 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
205 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
206
207 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
208
209 int rc;
210 if (pCfgReq->enmDir == PDMAUDIODIR_IN)
211 rc = nullCreateStreamIn( pStreamNull, pCfgReq, pCfgAcq);
212 else
213 rc = nullCreateStreamOut(pStreamNull, pCfgReq, pCfgAcq);
214
215 if (RT_SUCCESS(rc))
216 {
217 pStreamNull->pCfg = PDMAudioStrmCfgDup(pCfgAcq);
218 if (!pStreamNull->pCfg)
219 rc = VERR_NO_MEMORY;
220 }
221
222 return rc;
223}
224
225
226static int nullDestroyStreamIn(void)
227{
228 LogFlowFuncLeaveRC(VINF_SUCCESS);
229 return VINF_SUCCESS;
230}
231
232
233static int nullDestroyStreamOut(PNULLAUDIOSTREAM pStreamNull)
234{
235 RT_NOREF(pStreamNull);
236 return VINF_SUCCESS;
237}
238
239
240/**
241 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
242 */
243static DECLCALLBACK(int) drvHostNullAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
244{
245 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
246 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
247
248 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
249
250 if (!pStreamNull->pCfg) /* Not (yet) configured? Skip. */
251 return VINF_SUCCESS;
252
253 int rc;
254 if (pStreamNull->pCfg->enmDir == PDMAUDIODIR_IN)
255 rc = nullDestroyStreamIn();
256 else
257 rc = nullDestroyStreamOut(pStreamNull);
258
259 if (RT_SUCCESS(rc))
260 {
261 PDMAudioStrmCfgFree(pStreamNull->pCfg);
262 pStreamNull->pCfg = NULL;
263 }
264
265 return rc;
266}
267
268
269/**
270 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
271 */
272static DECLCALLBACK(int) drvHostNullAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface,
273 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
274{
275 RT_NOREF(pInterface, pStream, enmStreamCmd);
276 return VINF_SUCCESS;
277}
278
279
280/**
281 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
282 */
283static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
284{
285 RT_NOREF(pInterface, pStream);
286
287 return UINT32_MAX;
288}
289
290
291/**
292 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
293 */
294static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
295{
296 RT_NOREF(pInterface, pStream);
297
298 return UINT32_MAX;
299}
300
301
302/**
303 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
304 */
305static DECLCALLBACK(PDMAUDIOSTREAMSTS) drvHostNullAudioHA_StreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
306{
307 RT_NOREF(pInterface, pStream);
308 return PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED | PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
309}
310
311
312/**
313 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
314 */
315static DECLCALLBACK(int) drvHostNullAudioHA_StreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
316{
317 RT_NOREF(pInterface, pStream);
318 return VINF_SUCCESS;
319}
320
321
322/**
323 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
324 */
325static DECLCALLBACK(void *) drvHostNullAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
326{
327 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
328 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
329
330 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
331 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
332 return NULL;
333}
334
335
336/**
337 * Constructs a Null audio driver instance.
338 *
339 * @copydoc FNPDMDRVCONSTRUCT
340 */
341static DECLCALLBACK(int) drvHostNullAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
342{
343 RT_NOREF(pCfg, fFlags);
344 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
345 AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
346 /* pCfg is optional. */
347
348 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
349 LogRel(("Audio: Initializing NULL driver\n"));
350
351 /*
352 * Init the static parts.
353 */
354 pThis->pDrvIns = pDrvIns;
355 /* IBase */
356 pDrvIns->IBase.pfnQueryInterface = drvHostNullAudioQueryInterface;
357 /* IHostAudio */
358 pThis->IHostAudio.pfnInit = drvHostNullAudioHA_Init;
359 pThis->IHostAudio.pfnShutdown = drvHostNullAudioHA_Shutdown;
360 pThis->IHostAudio.pfnGetConfig = drvHostNullAudioHA_GetConfig;
361 pThis->IHostAudio.pfnGetStatus = drvHostNullAudioHA_GetStatus;
362 pThis->IHostAudio.pfnStreamCreate = drvHostNullAudioHA_StreamCreate;
363 pThis->IHostAudio.pfnStreamDestroy = drvHostNullAudioHA_StreamDestroy;
364 pThis->IHostAudio.pfnStreamControl = drvHostNullAudioHA_StreamControl;
365 pThis->IHostAudio.pfnStreamGetReadable = drvHostNullAudioHA_StreamGetReadable;
366 pThis->IHostAudio.pfnStreamGetWritable = drvHostNullAudioHA_StreamGetWritable;
367 pThis->IHostAudio.pfnStreamGetStatus = drvHostNullAudioHA_StreamGetStatus;
368 pThis->IHostAudio.pfnStreamIterate = drvHostNullAudioHA_StreamIterate;
369 pThis->IHostAudio.pfnStreamPlay = drvHostNullAudioHA_StreamPlay;
370 pThis->IHostAudio.pfnStreamCapture = drvHostNullAudioHA_StreamCapture;
371 pThis->IHostAudio.pfnSetCallback = NULL;
372 pThis->IHostAudio.pfnGetDevices = NULL;
373 pThis->IHostAudio.pfnStreamGetPending = NULL;
374 pThis->IHostAudio.pfnStreamPlayBegin = NULL;
375 pThis->IHostAudio.pfnStreamPlayEnd = NULL;
376 pThis->IHostAudio.pfnStreamCaptureBegin = NULL;
377 pThis->IHostAudio.pfnStreamCaptureEnd = NULL;
378
379 return VINF_SUCCESS;
380}
381
382
383/**
384 * Char driver registration record.
385 */
386const PDMDRVREG g_DrvHostNullAudio =
387{
388 /* u32Version */
389 PDM_DRVREG_VERSION,
390 /* szName */
391 "NullAudio",
392 /* szRCMod */
393 "",
394 /* szR0Mod */
395 "",
396 /* pszDescription */
397 "NULL audio host driver",
398 /* fFlags */
399 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
400 /* fClass. */
401 PDM_DRVREG_CLASS_AUDIO,
402 /* cMaxInstances */
403 ~0U,
404 /* cbInstance */
405 sizeof(DRVHOSTNULLAUDIO),
406 /* pfnConstruct */
407 drvHostNullAudioConstruct,
408 /* pfnDestruct */
409 NULL,
410 /* pfnRelocate */
411 NULL,
412 /* pfnIOCtl */
413 NULL,
414 /* pfnPowerOn */
415 NULL,
416 /* pfnReset */
417 NULL,
418 /* pfnSuspend */
419 NULL,
420 /* pfnResume */
421 NULL,
422 /* pfnAttach */
423 NULL,
424 /* pfnDetach */
425 NULL,
426 /* pfnPowerOff */
427 NULL,
428 /* pfnSoftReset */
429 NULL,
430 /* u32EndVersion */
431 PDM_DRVREG_VERSION
432};
433
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