VirtualBox

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

Last change on this file since 56289 was 56289, checked in by vboxsync, 9 years ago

Removed unused header.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: DrvHostNullAudio.cpp 56289 2015-06-09 13:31:22Z 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-2015 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#include "DrvAudio.h"
44#include "AudioMixBuffer.h"
45
46#include "VBoxDD.h"
47
48#include <iprt/alloc.h>
49#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
50#include <VBox/vmm/pdmaudioifs.h>
51
52#ifdef LOG_GROUP
53# undef LOG_GROUP
54#endif
55#define LOG_GROUP LOG_GROUP_DEV_AUDIO
56#include <VBox/log.h>
57
58typedef struct NULLAUDIOSTREAMOUT
59{
60 /** Note: Always must come first! */
61 PDMAUDIOHSTSTRMOUT hw;
62 uint64_t u64TicksLast;
63} NULLAUDIOSTREAMOUT;
64
65typedef struct NULLAUDIOSTREAMIN
66{
67 /** Note: Always must come first! */
68 PDMAUDIOHSTSTRMIN hw;
69} NULLAUDIOSTREAMIN;
70
71/**
72 * NULL audio driver instance data.
73 * @implements PDMIAUDIOCONNECTOR
74 */
75typedef struct DRVHOSTNULLAUDIO
76{
77 /** Pointer to the driver instance structure. */
78 PPDMDRVINS pDrvIns;
79 /** Pointer to host audio interface. */
80 PDMIHOSTAUDIO IHostAudio;
81} DRVHOSTNULLAUDIO, *PDRVHOSTNULLAUDIO;
82
83/*******************************************PDM_AUDIO_DRIVER******************************/
84
85
86static DECLCALLBACK(int) drvHostNullAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
87{
88 NOREF(pInterface);
89 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
90
91 pCfg->cbStreamOut = sizeof(NULLAUDIOSTREAMOUT);
92 pCfg->cbStreamIn = sizeof(NULLAUDIOSTREAMIN);
93
94 pCfg->cMaxHstStrmsOut = 1; /* Output */
95 pCfg->cMaxHstStrmsIn = 2; /* Line input + microphone input. */
96
97 return VINF_SUCCESS;
98}
99
100static DECLCALLBACK(int) drvHostNullAudioInit(PPDMIHOSTAUDIO pInterface)
101{
102 NOREF(pInterface);
103
104 return VINF_SUCCESS;
105}
106
107static DECLCALLBACK(int) drvHostNullAudioInitIn(PPDMIHOSTAUDIO pInterface,
108 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
109 PDMAUDIORECSOURCE enmRecSource,
110 uint32_t *pcSamples)
111{
112 NOREF(pInterface);
113 NOREF(enmRecSource);
114
115 /* Just adopt the wanted stream configuration. */
116 int rc = drvAudioStreamCfgToProps(pCfg, &pHstStrmIn->Props);
117 if (RT_SUCCESS(rc))
118 {
119 if (pcSamples)
120 *pcSamples = _1K;
121 }
122
123 return VINF_SUCCESS;
124}
125
126static DECLCALLBACK(int) drvHostNullAudioInitOut(PPDMIHOSTAUDIO pInterface,
127 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
128 uint32_t *pcSamples)
129{
130 NOREF(pInterface);
131
132 /* Just adopt the wanted stream configuration. */
133 int rc = drvAudioStreamCfgToProps(pCfg, &pHstStrmOut->Props);
134 if (RT_SUCCESS(rc))
135 {
136 NULLAUDIOSTREAMOUT *pNullStrmOut = (NULLAUDIOSTREAMOUT *)pHstStrmOut;
137 pNullStrmOut->u64TicksLast = 0;
138 if (pcSamples)
139 *pcSamples = _1K;
140 }
141
142 return rc;
143}
144
145static DECLCALLBACK(bool) drvHostNullAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
146{
147 NOREF(pInterface);
148 NOREF(enmDir);
149 return true; /* Always all enabled. */
150}
151
152static DECLCALLBACK(int) drvHostNullAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
153 uint32_t *pcSamplesPlayed)
154{
155 PDRVHOSTNULLAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTNULLAUDIO, IHostAudio);
156 NULLAUDIOSTREAMOUT *pNullStrmOut = (NULLAUDIOSTREAMOUT *)pHstStrmOut;
157
158 /* Consume as many samples as would be played at the current frequency since last call. */
159 uint32_t csLive = drvAudioHstOutSamplesLive(pHstStrmOut, NULL /* pcStreamsLive */);
160 uint64_t u64TicksNow = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
161 uint64_t u64TicksElapsed = u64TicksNow - pNullStrmOut->u64TicksLast;
162 uint64_t u64TicksFreq = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
163
164 /* Remember when samples were consumed. */
165 pNullStrmOut->u64TicksLast = u64TicksNow;
166
167 /* Minimize the rounding error by adding 0.5: samples = int((u64TicksElapsed * samplesFreq) / u64TicksFreq + 0.5).
168 * If rounding is not taken into account then the playback rate will be consistently lower that expected.
169 */
170 uint64_t cSamplesPlayed = (2 * u64TicksElapsed * pHstStrmOut->Props.uHz + u64TicksFreq) / u64TicksFreq / 2;
171
172 /* Don't play more than available. */
173 if (cSamplesPlayed > csLive)
174 cSamplesPlayed = csLive;
175
176 AudioMixBufFinish(&pHstStrmOut->MixBuf, cSamplesPlayed);
177
178 if (pcSamplesPlayed)
179 *pcSamplesPlayed = cSamplesPlayed;
180
181 return VINF_SUCCESS;
182}
183
184static DECLCALLBACK(int) drvHostNullAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
185 uint32_t *pcSamplesCaptured)
186{
187 /* Never capture anything. */
188 if (pcSamplesCaptured)
189 *pcSamplesCaptured = 0;
190
191 return VINF_SUCCESS;
192}
193
194static DECLCALLBACK(int) drvHostNullAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
195 PDMAUDIOSTREAMCMD enmStreamCmd)
196{
197 NOREF(pInterface);
198 NOREF(pHstStrmIn);
199 NOREF(enmStreamCmd);
200
201 return VINF_SUCCESS;
202}
203
204static DECLCALLBACK(int) drvHostNullAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
205 PDMAUDIOSTREAMCMD enmStreamCmd)
206{
207 NOREF(pInterface);
208 NOREF(pHstStrmOut);
209 NOREF(enmStreamCmd);
210
211 return VINF_SUCCESS;
212}
213
214static DECLCALLBACK(int) drvHostNullAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
215{
216 return VINF_SUCCESS;
217}
218
219static DECLCALLBACK(int) drvHostNullAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
220{
221 return VINF_SUCCESS;
222}
223
224/**
225 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
226 */
227static DECLCALLBACK(void *) drvHostNullAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
228{
229 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
230 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
231
232 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
233 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
234 return NULL;
235}
236
237static DECLCALLBACK(void) drvHostNullAudioShutdown(PPDMIHOSTAUDIO pInterface)
238{
239 NOREF(pInterface);
240}
241
242/**
243 * Constructs a Null audio driver instance.
244 *
245 * @copydoc FNPDMDRVCONSTRUCT
246 */
247static DECLCALLBACK(int) drvHostNullAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
248{
249 AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
250 /* pCfg is optional. */
251
252 PDRVHOSTNULLAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTNULLAUDIO);
253 LogRel(("Audio: Initializing NULL driver\n"));
254
255 /*
256 * Init the static parts.
257 */
258 pThis->pDrvIns = pDrvIns;
259 /* IBase */
260 pDrvIns->IBase.pfnQueryInterface = drvHostNullAudioQueryInterface;
261 /* IHostAudio */
262 PDMAUDIO_IHOSTAUDIO_CALLBACKS(drvHostNullAudio);
263
264 return VINF_SUCCESS;
265}
266
267/**
268 * Char driver registration record.
269 */
270const PDMDRVREG g_DrvHostNullAudio =
271{
272 /* u32Version */
273 PDM_DRVREG_VERSION,
274 /* szName */
275 "NullAudio",
276 /* szRCMod */
277 "",
278 /* szR0Mod */
279 "",
280 /* pszDescription */
281 "NULL audio host driver",
282 /* fFlags */
283 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
284 /* fClass. */
285 PDM_DRVREG_CLASS_AUDIO,
286 /* cMaxInstances */
287 ~0U,
288 /* cbInstance */
289 sizeof(DRVHOSTNULLAUDIO),
290 /* pfnConstruct */
291 drvHostNullAudioConstruct,
292 /* pfnDestruct */
293 NULL,
294 /* pfnRelocate */
295 NULL,
296 /* pfnIOCtl */
297 NULL,
298 /* pfnPowerOn */
299 NULL,
300 /* pfnReset */
301 NULL,
302 /* pfnSuspend */
303 NULL,
304 /* pfnResume */
305 NULL,
306 /* pfnAttach */
307 NULL,
308 /* pfnDetach */
309 NULL,
310 /* pfnPowerOff */
311 NULL,
312 /* pfnSoftReset */
313 NULL,
314 /* u32EndVersion */
315 PDM_DRVREG_VERSION
316};
317
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