VirtualBox

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

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

Audio: Removed PDMIHOSTAUDIO::pfnSetCallback (replaced by PDMIAUDIONOTIFYFROMHOST). bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/* $Id: DrvHostAudioNull.cpp 88362 2021-04-05 00:31:17Z vboxsync $ */
2/** @file
3 * Host audio driver - NULL.
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 "VBoxDD.h"
58
59
60/*********************************************************************************************************************************
61* Structures and Typedefs *
62*********************************************************************************************************************************/
63typedef struct NULLAUDIOSTREAM
64{
65 /** The stream's acquired configuration. */
66 PPDMAUDIOSTREAMCFG pCfg;
67} NULLAUDIOSTREAM, *PNULLAUDIOSTREAM;
68
69/**
70 * NULL audio driver instance data.
71 * @implements PDMIAUDIOCONNECTOR
72 */
73typedef struct DRVHOSTNULLAUDIO
74{
75 /** Pointer to the driver instance structure. */
76 PPDMDRVINS pDrvIns;
77 /** Pointer to host audio interface. */
78 PDMIHOSTAUDIO IHostAudio;
79} DRVHOSTNULLAUDIO, *PDRVHOSTNULLAUDIO;
80
81
82
83/**
84 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig}
85 */
86static DECLCALLBACK(int) drvHostNullAudioHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
87{
88 NOREF(pInterface);
89 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
90
91 RTStrPrintf2(pBackendCfg->szName, sizeof(pBackendCfg->szName), "NULL audio");
92
93 pBackendCfg->cbStreamOut = sizeof(NULLAUDIOSTREAM);
94 pBackendCfg->cbStreamIn = sizeof(NULLAUDIOSTREAM);
95
96 pBackendCfg->cMaxStreamsOut = 1; /* Output */
97 pBackendCfg->cMaxStreamsIn = 2; /* Line input + microphone input. */
98
99 return VINF_SUCCESS;
100}
101
102
103/**
104 * @interface_method_impl{PDMIHOSTAUDIO,pfnInit}
105 */
106static DECLCALLBACK(int) drvHostNullAudioHA_Init(PPDMIHOSTAUDIO pInterface)
107{
108 NOREF(pInterface);
109
110 LogFlowFuncLeaveRC(VINF_SUCCESS);
111 return VINF_SUCCESS;
112}
113
114
115/**
116 * @interface_method_impl{PDMIHOSTAUDIO,pfnShutdown}
117 */
118static DECLCALLBACK(void) drvHostNullAudioHA_Shutdown(PPDMIHOSTAUDIO pInterface)
119{
120 RT_NOREF(pInterface);
121}
122
123
124/**
125 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus}
126 */
127static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostNullAudioHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
128{
129 RT_NOREF(enmDir);
130 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
131
132 return PDMAUDIOBACKENDSTS_RUNNING;
133}
134
135
136/**
137 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}
138 */
139static DECLCALLBACK(int) drvHostNullAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
140 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
141{
142 RT_NOREF(pInterface, pStream, pvBuf);
143
144 /* The bitbucket never overflows. */
145 *pcbWritten = cbBuf;
146 return VINF_SUCCESS;
147}
148
149
150/**
151 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture}
152 */
153static DECLCALLBACK(int) drvHostNullAudioHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
154 void *pvBuf, uint32_t uBufSize, uint32_t *puRead)
155{
156 RT_NOREF(pInterface, pStream);
157
158 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
159
160 /* Return silence. */
161 Assert(pStreamNull->pCfg);
162 PDMAudioPropsClearBuffer(&pStreamNull->pCfg->Props, pvBuf, uBufSize, PDMAUDIOPCMPROPS_B2F(&pStreamNull->pCfg->Props, uBufSize));
163
164 if (puRead)
165 *puRead = uBufSize;
166
167 return VINF_SUCCESS;
168}
169
170
171static int nullCreateStreamIn(PNULLAUDIOSTREAM pStreamNull, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
172{
173 RT_NOREF(pStreamNull, pCfgReq, pCfgAcq);
174
175 return VINF_SUCCESS;
176}
177
178
179static int nullCreateStreamOut(PNULLAUDIOSTREAM pStreamNull, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
180{
181 RT_NOREF(pStreamNull, pCfgReq, pCfgAcq);
182
183 return VINF_SUCCESS;
184}
185
186
187/**
188 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
189 */
190static DECLCALLBACK(int) drvHostNullAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
191 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)
192{
193 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
194 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
195 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER);
196 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER);
197
198 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
199
200 int rc;
201 if (pCfgReq->enmDir == PDMAUDIODIR_IN)
202 rc = nullCreateStreamIn( pStreamNull, pCfgReq, pCfgAcq);
203 else
204 rc = nullCreateStreamOut(pStreamNull, pCfgReq, pCfgAcq);
205
206 if (RT_SUCCESS(rc))
207 {
208 pStreamNull->pCfg = PDMAudioStrmCfgDup(pCfgAcq);
209 if (!pStreamNull->pCfg)
210 rc = VERR_NO_MEMORY;
211 }
212
213 return rc;
214}
215
216
217static int nullDestroyStreamIn(void)
218{
219 LogFlowFuncLeaveRC(VINF_SUCCESS);
220 return VINF_SUCCESS;
221}
222
223
224static int nullDestroyStreamOut(PNULLAUDIOSTREAM pStreamNull)
225{
226 RT_NOREF(pStreamNull);
227 return VINF_SUCCESS;
228}
229
230
231/**
232 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy}
233 */
234static DECLCALLBACK(int) drvHostNullAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
235{
236 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
237 AssertPtrReturn(pStream, VERR_INVALID_POINTER);
238
239 PNULLAUDIOSTREAM pStreamNull = (PNULLAUDIOSTREAM)pStream;
240
241 if (!pStreamNull->pCfg) /* Not (yet) configured? Skip. */
242 return VINF_SUCCESS;
243
244 int rc;
245 if (pStreamNull->pCfg->enmDir == PDMAUDIODIR_IN)
246 rc = nullDestroyStreamIn();
247 else
248 rc = nullDestroyStreamOut(pStreamNull);
249
250 if (RT_SUCCESS(rc))
251 {
252 PDMAudioStrmCfgFree(pStreamNull->pCfg);
253 pStreamNull->pCfg = NULL;
254 }
255
256 return rc;
257}
258
259
260/**
261 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl}
262 */
263static DECLCALLBACK(int) drvHostNullAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface,
264 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
265{
266 RT_NOREF(pInterface, pStream, enmStreamCmd);
267 return VINF_SUCCESS;
268}
269
270
271/**
272 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable}
273 */
274static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
275{
276 RT_NOREF(pInterface, pStream);
277
278 return UINT32_MAX;
279}
280
281
282/**
283 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable}
284 */
285static DECLCALLBACK(uint32_t) drvHostNullAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
286{
287 RT_NOREF(pInterface, pStream);
288
289 return UINT32_MAX;
290}
291
292
293/**
294 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetStatus}
295 */
296static DECLCALLBACK(PDMAUDIOSTREAMSTS) drvHostNullAudioHA_StreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
297{
298 RT_NOREF(pInterface, pStream);
299 return PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED | PDMAUDIOSTREAMSTS_FLAGS_ENABLED;
300}
301
302
303/**
304 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamIterate}
305 */
306static DECLCALLBACK(int) drvHostNullAudioHA_StreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
307{
308 RT_NOREF(pInterface, pStream);
309 return VINF_SUCCESS;
310}
311
312
313/**
314 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
315 */
316static DECLCALLBACK(void *) drvHostNullAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
317{
318 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
319 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
320
321 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
322 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
323 return NULL;
324}
325
326
327/**
328 * Constructs a Null audio driver instance.
329 *
330 * @copydoc FNPDMDRVCONSTRUCT
331 */
332static DECLCALLBACK(int) drvHostNullAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
333{
334 RT_NOREF(pCfg, fFlags);
335 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
336 AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
337 /* pCfg is optional. */
338
339 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
340 LogRel(("Audio: Initializing NULL driver\n"));
341
342 /*
343 * Init the static parts.
344 */
345 pThis->pDrvIns = pDrvIns;
346 /* IBase */
347 pDrvIns->IBase.pfnQueryInterface = drvHostNullAudioQueryInterface;
348 /* IHostAudio */
349 pThis->IHostAudio.pfnInit = drvHostNullAudioHA_Init;
350 pThis->IHostAudio.pfnShutdown = drvHostNullAudioHA_Shutdown;
351 pThis->IHostAudio.pfnGetConfig = drvHostNullAudioHA_GetConfig;
352 pThis->IHostAudio.pfnGetStatus = drvHostNullAudioHA_GetStatus;
353 pThis->IHostAudio.pfnStreamCreate = drvHostNullAudioHA_StreamCreate;
354 pThis->IHostAudio.pfnStreamDestroy = drvHostNullAudioHA_StreamDestroy;
355 pThis->IHostAudio.pfnStreamControl = drvHostNullAudioHA_StreamControl;
356 pThis->IHostAudio.pfnStreamGetReadable = drvHostNullAudioHA_StreamGetReadable;
357 pThis->IHostAudio.pfnStreamGetWritable = drvHostNullAudioHA_StreamGetWritable;
358 pThis->IHostAudio.pfnStreamGetStatus = drvHostNullAudioHA_StreamGetStatus;
359 pThis->IHostAudio.pfnStreamIterate = drvHostNullAudioHA_StreamIterate;
360 pThis->IHostAudio.pfnStreamPlay = drvHostNullAudioHA_StreamPlay;
361 pThis->IHostAudio.pfnStreamCapture = drvHostNullAudioHA_StreamCapture;
362 pThis->IHostAudio.pfnGetDevices = NULL;
363 pThis->IHostAudio.pfnStreamGetPending = NULL;
364 pThis->IHostAudio.pfnStreamPlayBegin = NULL;
365 pThis->IHostAudio.pfnStreamPlayEnd = NULL;
366 pThis->IHostAudio.pfnStreamCaptureBegin = NULL;
367 pThis->IHostAudio.pfnStreamCaptureEnd = NULL;
368
369 return VINF_SUCCESS;
370}
371
372
373/**
374 * Char driver registration record.
375 */
376const PDMDRVREG g_DrvHostNullAudio =
377{
378 /* u32Version */
379 PDM_DRVREG_VERSION,
380 /* szName */
381 "NullAudio",
382 /* szRCMod */
383 "",
384 /* szR0Mod */
385 "",
386 /* pszDescription */
387 "NULL audio host driver",
388 /* fFlags */
389 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
390 /* fClass. */
391 PDM_DRVREG_CLASS_AUDIO,
392 /* cMaxInstances */
393 ~0U,
394 /* cbInstance */
395 sizeof(DRVHOSTNULLAUDIO),
396 /* pfnConstruct */
397 drvHostNullAudioConstruct,
398 /* pfnDestruct */
399 NULL,
400 /* pfnRelocate */
401 NULL,
402 /* pfnIOCtl */
403 NULL,
404 /* pfnPowerOn */
405 NULL,
406 /* pfnReset */
407 NULL,
408 /* pfnSuspend */
409 NULL,
410 /* pfnResume */
411 NULL,
412 /* pfnAttach */
413 NULL,
414 /* pfnDetach */
415 NULL,
416 /* pfnPowerOff */
417 NULL,
418 /* pfnSoftReset */
419 NULL,
420 /* u32EndVersion */
421 PDM_DRVREG_VERSION
422};
423
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