VirtualBox

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

Last change on this file since 65919 was 65694, checked in by vboxsync, 8 years ago

Audio: Removed PDMAUDIOSTRMSTS_FLAG_DATA_READABLE / PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE and added IHostAudio::pfnStreamGetReadable() and IHostAudio::pfnStreamGetWritable() instead.

Split up drvAudioStreamPlay() into drvAudioStreamPlayNonInterleaved() and drvAudioStreamPlayRaw() for handling different audio data layouts.

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