VirtualBox

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

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

Audio: Remove DEV_AUDIO logging group and split it up into per device and driver groups for finer grained logging

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