VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvHostAudioNull.cpp@ 89224

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

Audio: Added an fImmediate indicator to the pfnStreamDestroy methods so the backend knows whether it's okay to continue draining the stream or if it must be destroyed without delay. The latter is typically only for shutdown and driver plumbing. This helps quite a bit for HDA/CoreAudio/knoppix. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: DrvHostAudioNull.cpp 89213 2021-05-21 10:00:12Z vboxsync $ */
2/** @file
3 * Host audio driver - NULL (bitbucket).
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
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
25
26#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
27#include <VBox/log.h>
28#include <VBox/vmm/pdmaudioifs.h>
29#include <VBox/vmm/pdmaudioinline.h>
30
31#include "VBoxDD.h"
32
33
34/*********************************************************************************************************************************
35* Structures and Typedefs *
36*********************************************************************************************************************************/
37/** Null audio stream. */
38typedef struct NULLAUDIOSTREAM
39{
40 /** Common part. */
41 PDMAUDIOBACKENDSTREAM Core;
42 /** The stream's acquired configuration. */
43 PDMAUDIOSTREAMCFG Cfg;
44} NULLAUDIOSTREAM;
45/** Pointer to a null audio stream. */
46typedef NULLAUDIOSTREAM *PNULLAUDIOSTREAM;
47
48
49
50/**
51 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
52 */
53static DECLCALLBACK(int) drvHostNullAudioHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
54{
55 NOREF(pInterface);
56 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
57
58 /*
59 * Fill in the config structure.
60 */
61 RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "NULL audio");
62 pBackendCfg->cbStream = sizeof(NULLAUDIOSTREAM);
63 pBackendCfg->fFlags = 0;
64 pBackendCfg->cMaxStreamsOut = 1; /* Output */
65 pBackendCfg->cMaxStreamsIn = 2; /* Line input + microphone input. */
66
67 return VINF_SUCCESS;
68}
69
70
71/**
72 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
73 */
74static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostNullAudioHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
75{
76 RT_NOREF(pInterface, enmDir);
77 return PDMAUDIOBACKENDSTS_RUNNING;
78}
79
80
81/**
82 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
83 */
84static DECLCALLBACK(int) drvHostNullAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
85 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
86{
87 RT_NOREF(pInterface);
88 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
89 AssertPtrReturn(pStreamNull, VERR_INVALID_POINTER);
90 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
91 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
92
93 PDMAudioStrmCfgCopy(&pStreamNull->Cfg, pCfgAcq);
94 return VINF_SUCCESS;
95}
96
97
98/**
99 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
100 */
101static DECLCALLBACK(int) drvHostNullAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
102 bool fImmediate)
103{
104 RT_NOREF(pInterface, pStream, fImmediate);
105 return VINF_SUCCESS;
106}
107
108
109/**
110 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable}
111 */
112static DECLCALLBACK(int) drvHostNullAudioHA_StreamControlStub(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
113{
114 RT_NOREF(pInterface, pStream);
115 return VINF_SUCCESS;
116}
117
118
119/**
120 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
121 */
122static DECLCALLBACK(int) drvHostNullAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface,
123 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
124{
125 /** @todo r=bird: I'd like to get rid of this pfnStreamControl method,
126 * replacing it with individual StreamXxxx methods. That would save us
127 * potentally huge switches and more easily see which drivers implement
128 * which operations (grep for pfnStreamXxxx). */
129 switch (enmStreamCmd)
130 {
131 case PDMAUDIOSTREAMCMD_ENABLE:
132 return drvHostNullAudioHA_StreamControlStub(pInterface, pStream);
133 case PDMAUDIOSTREAMCMD_DISABLE:
134 return drvHostNullAudioHA_StreamControlStub(pInterface, pStream);
135 case PDMAUDIOSTREAMCMD_PAUSE:
136 return drvHostNullAudioHA_StreamControlStub(pInterface, pStream);
137 case PDMAUDIOSTREAMCMD_RESUME:
138 return drvHostNullAudioHA_StreamControlStub(pInterface, pStream);
139 case PDMAUDIOSTREAMCMD_DRAIN:
140 return drvHostNullAudioHA_StreamControlStub(pInterface, pStream);
141
142 case PDMAUDIOSTREAMCMD_END:
143 case PDMAUDIOSTREAMCMD_32BIT_HACK:
144 case PDMAUDIOSTREAMCMD_INVALID:
145 /* no default*/
146 break;
147 }
148 return VERR_NOT_SUPPORTED;
149}
150
151
152/**
153 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
154 */
155static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
156{
157 RT_NOREF(pInterface, pStream);
158 /** @todo rate limit this? */
159 return UINT32_MAX;
160}
161
162
163/**
164 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
165 */
166static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
167{
168 RT_NOREF(pInterface, pStream);
169 return UINT32_MAX;
170}
171
172
173/**
174 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetPending}
175 */
176static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
177{
178 RT_NOREF(pInterface, pStream);
179 return 0;
180}
181
182
183/**
184 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetState}
185 */
186static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvHostNullAudioHA_StreamGetState(PPDMIHOSTAUDIO pInterface,
187 PPDMAUDIOBACKENDSTREAM pStream)
188{
189 RT_NOREF(pInterface);
190 AssertPtrReturn(pStream, PDMHOSTAUDIOSTREAMSTATE_INVALID);
191#if 0
192 /* Bit bucket appraoch where we ignore the output and silence the input buffers. */
193 return PDMHOSTAUDIOSTREAMSTATE_OKAY;
194#else
195 /* Approach where the mixer in the devices skips us and saves a few CPU cycles. */
196 return PDMHOSTAUDIOSTREAMSTATE_INACTIVE;
197#endif
198}
199
200
201/**
202 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
203 */
204static DECLCALLBACK(int) drvHostNullAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
205 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
206{
207 RT_NOREF(pInterface, pStream, pvBuf);
208
209 /* The bitbucket never overflows. */
210 *pcbWritten = cbBuf;
211 return VINF_SUCCESS;
212}
213
214
215/**
216 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
217 */
218static DECLCALLBACK(int) drvHostNullAudioHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
219 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
220{
221 RT_NOREF(pInterface);
222 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
223
224 /** @todo rate limit this? */
225
226 /* Return silence. */
227 PDMAudioPropsClearBuffer(&pStreamNull->Cfg.Props, pvBuf, cbBuf,
228 PDMAudioPropsBytesToFrames(&pStreamNull->Cfg.Props, cbBuf));
229 *pcbRead = cbBuf;
230 return VINF_SUCCESS;
231}
232
233
234/**
235 * This is used directly by DrvAudio when a backend fails to initialize in a
236 * non-fatal manner.
237 */
238DECL_HIDDEN_CONST(PDMIHOSTAUDIO) const g_DrvHostAudioNull =
239{
240 /* .pfnGetConfig =*/ drvHostNullAudioHA_GetConfig,
241 /* .pfnGetDevices =*/ NULL,
242 /* .pfnGetStatus =*/ drvHostNullAudioHA_GetStatus,
243 /* .pfnDoOnWorkerThread =*/ NULL,
244 /* .pfnStreamConfigHint =*/ NULL,
245 /* .pfnStreamCreate =*/ drvHostNullAudioHA_StreamCreate,
246 /* .pfnStreamInitAsync =*/ NULL,
247 /* .pfnStreamDestroy =*/ drvHostNullAudioHA_StreamDestroy,
248 /* .pfnStreamNotifyDeviceChanged =*/ NULL,
249 /* .pfnStreamControl =*/ drvHostNullAudioHA_StreamControl,
250 /* .pfnStreamGetReadable =*/ drvHostNullAudioHA_StreamGetReadable,
251 /* .pfnStreamGetWritable =*/ drvHostNullAudioHA_StreamGetWritable,
252 /* .pfnStreamGetPending =*/ drvHostNullAudioHA_StreamGetPending,
253 /* .pfnStreamGetState =*/ drvHostNullAudioHA_StreamGetState,
254 /* .pfnStreamPlay =*/ drvHostNullAudioHA_StreamPlay,
255 /* .pfnStreamCapture =*/ drvHostNullAudioHA_StreamCapture,
256};
257
258
259/**
260 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
261 */
262static DECLCALLBACK(void *) drvHostNullAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
263{
264 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
265 PPDMIHOSTAUDIO pThis = PDMINS_2_DATA(pDrvIns, PPDMIHOSTAUDIO);
266
267 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
268 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, pThis);
269 return NULL;
270}
271
272
273/**
274 * Constructs a Null audio driver instance.
275 *
276 * @copydoc FNPDMDRVCONSTRUCT
277 */
278static DECLCALLBACK(int) drvHostNullAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
279{
280 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
281 PPDMIHOSTAUDIO pThis = PDMINS_2_DATA(pDrvIns, PPDMIHOSTAUDIO);
282 RT_NOREF(pCfg, fFlags);
283 LogRel(("Audio: Initializing NULL driver\n"));
284
285 /*
286 * Init the static parts.
287 */
288 /* IBase */
289 pDrvIns->IBase.pfnQueryInterface = drvHostNullAudioQueryInterface;
290 /* IHostAudio */
291 *pThis = g_DrvHostAudioNull;
292
293 return VINF_SUCCESS;
294}
295
296
297/**
298 * Char driver registration record.
299 */
300const PDMDRVREG g_DrvHostNullAudio =
301{
302 /* u32Version */
303 PDM_DRVREG_VERSION,
304 /* szName */
305 "NullAudio",
306 /* szRCMod */
307 "",
308 /* szR0Mod */
309 "",
310 /* pszDescription */
311 "NULL audio host driver",
312 /* fFlags */
313 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
314 /* fClass. */
315 PDM_DRVREG_CLASS_AUDIO,
316 /* cMaxInstances */
317 ~0U,
318 /* cbInstance */
319 sizeof(PDMIHOSTAUDIO),
320 /* pfnConstruct */
321 drvHostNullAudioConstruct,
322 /* pfnDestruct */
323 NULL,
324 /* pfnRelocate */
325 NULL,
326 /* pfnIOCtl */
327 NULL,
328 /* pfnPowerOn */
329 NULL,
330 /* pfnReset */
331 NULL,
332 /* pfnSuspend */
333 NULL,
334 /* pfnResume */
335 NULL,
336 /* pfnAttach */
337 NULL,
338 /* pfnDetach */
339 NULL,
340 /* pfnPowerOff */
341 NULL,
342 /* pfnSoftReset */
343 NULL,
344 /* u32EndVersion */
345 PDM_DRVREG_VERSION
346};
347
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