VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/AudioDriver.cpp

Last change on this file was 98278, checked in by vboxsync, 16 months ago

Main/src-client: Some more rc -> hrc/vrc stuff found by grep. A build fix. bugref:10223

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 KB
RevLine 
[70533]1/* $Id: AudioDriver.cpp 98278 2023-01-24 11:55:00Z vboxsync $ */
2/** @file
3 * VirtualBox audio base class for Main audio drivers.
4 */
5
6/*
[98103]7 * Copyright (C) 2018-2023 Oracle and/or its affiliates.
[70533]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[70533]26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
33#include "LoggingNew.h"
34
35#include <VBox/log.h>
36#include <VBox/vmm/cfgm.h>
37#include <VBox/vmm/pdmaudioifs.h>
38#include <VBox/vmm/pdmapi.h>
39#include <VBox/vmm/pdmdrv.h>
[93444]40#include <VBox/vmm/vmmr3vtable.h>
[70533]41
42#include "AudioDriver.h"
43#include "ConsoleImpl.h"
44
45AudioDriver::AudioDriver(Console *pConsole)
46 : mpConsole(pConsole)
47 , mfAttached(false)
48{
49}
50
[81674]51
[70533]52AudioDriver::~AudioDriver(void)
53{
54}
55
56
[81674]57AudioDriver &AudioDriver::operator=(AudioDriver const &a_rThat) RT_NOEXCEPT
58{
59 mpConsole = a_rThat.mpConsole;
60 mCfg = a_rThat.mCfg;
61 mfAttached = a_rThat.mfAttached;
62
63 return *this;
64}
65
66
[70564]67/**
68 * Initializes the audio driver with a certain (device) configuration.
[70579]69 *
[70564]70 * @returns VBox status code.
[70579]71 * @param pCfg Audio driver configuration to use.
[70564]72 */
[70579]73int AudioDriver::InitializeConfig(AudioDriverCfg *pCfg)
[70563]74{
75 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
76
[70644]77 /* Sanity. */
78 AssertReturn(pCfg->strDev.isNotEmpty(), VERR_INVALID_PARAMETER);
79 AssertReturn(pCfg->uLUN != UINT8_MAX, VERR_INVALID_PARAMETER);
80 AssertReturn(pCfg->strName.isNotEmpty(), VERR_INVALID_PARAMETER);
81
[70563]82 /* Apply configuration. */
83 mCfg = *pCfg;
84
85 return VINF_SUCCESS;
86}
87
[70579]88
[70533]89/**
[70579]90 * Attaches the driver via EMT, if configured.
91 *
[88300]92 * @returns VBox status code.
[93444]93 * @param pUVM The user mode VM handle for talking to EMT.
94 * @param pVMM The VMM ring-3 vtable.
95 * @param pAutoLock The callers auto lock instance. Can be NULL if not
96 * locked.
[70579]97 */
[93444]98int AudioDriver::doAttachDriverViaEmt(PUVM pUVM, PCVMMR3VTABLE pVMM, util::AutoWriteLock *pAutoLock)
[70579]99{
100 if (!isConfigured())
101 return VINF_SUCCESS;
102
103 PVMREQ pReq;
[93444]104 int vrc = pVMM->pfnVMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
105 (PFNRT)attachDriverOnEmt, 1, this);
[70579]106 if (vrc == VERR_TIMEOUT)
107 {
108 /* Release the lock before a blocking VMR3* call (EMT might wait for it, @bugref{7648})! */
109 if (pAutoLock)
110 pAutoLock->release();
111
[93444]112 vrc = pVMM->pfnVMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
[70579]113
114 if (pAutoLock)
115 pAutoLock->acquire();
116 }
117
118 AssertRC(vrc);
[93444]119 pVMM->pfnVMR3ReqFree(pReq);
[70579]120
121 return vrc;
122}
123
124
125/**
[70533]126 * Configures the audio driver (to CFGM) and attaches it to the audio chain.
[70547]127 * Does nothing if the audio driver already is attached.
[70533]128 *
[70564]129 * @returns VBox status code.
[70536]130 * @param pThis Audio driver to detach.
[70533]131 */
132/* static */
[70579]133DECLCALLBACK(int) AudioDriver::attachDriverOnEmt(AudioDriver *pThis)
[70533]134{
135 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
136
137 Console::SafeVMPtrQuiet ptrVM(pThis->mpConsole);
138 Assert(ptrVM.isOk());
139
140 if (pThis->mfAttached) /* Already attached? Bail out. */
[70563]141 {
142 LogFunc(("%s: Already attached\n", pThis->mCfg.strName.c_str()));
[70533]143 return VINF_SUCCESS;
[70563]144 }
[70533]145
[70563]146 AudioDriverCfg *pCfg = &pThis->mCfg;
[70533]147
[70544]148 LogFunc(("strName=%s, strDevice=%s, uInst=%u, uLUN=%u\n",
[70644]149 pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN));
[70536]150
[70670]151 /* Detach the driver chain from the audio device first. */
[94919]152 int vrc = ptrVM.vtable()->pfnPDMR3DeviceDetach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN, 0 /* fFlags */);
153 if (RT_SUCCESS(vrc))
[70670]154 {
[94919]155 vrc = pThis->configure(pCfg->uLUN, true /* Attach */);
156 if (RT_SUCCESS(vrc))
157 vrc = ptrVM.vtable()->pfnPDMR3DriverAttach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN,
158 0 /* fFlags */, NULL /* ppBase */);
[70670]159 }
160
[94919]161 if (RT_SUCCESS(vrc))
[70536]162 {
163 pThis->mfAttached = true;
[70644]164 LogRel2(("%s: Driver attached (LUN #%u)\n", pCfg->strName.c_str(), pCfg->uLUN));
[70533]165 }
[70536]166 else
[98278]167 LogRel(("%s: Failed to attach audio driver, vrc=%Rrc\n", pCfg->strName.c_str(), vrc));
[70533]168
[94919]169 LogFunc(("Returning %Rrc\n", vrc));
170 return vrc;
[70533]171}
172
[70579]173
[70533]174/**
[70579]175 * Detatches the driver via EMT, if configured.
176 *
[88300]177 * @returns VBox status code.
[93444]178 * @param pUVM The user mode VM handle for talking to EMT.
179 * @param pVMM The VMM ring-3 vtable.
180 * @param pAutoLock The callers auto lock instance. Can be NULL if not
181 * locked.
[70579]182 */
[93444]183int AudioDriver::doDetachDriverViaEmt(PUVM pUVM, PCVMMR3VTABLE pVMM, util::AutoWriteLock *pAutoLock)
[70579]184{
185 if (!isConfigured())
186 return VINF_SUCCESS;
187
188 PVMREQ pReq;
[93444]189 int vrc = pVMM->pfnVMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, 0 /* no wait! */, VMREQFLAGS_VBOX_STATUS,
190 (PFNRT)detachDriverOnEmt, 1, this);
[70579]191 if (vrc == VERR_TIMEOUT)
192 {
193 /* Release the lock before a blocking VMR3* call (EMT might wait for it, @bugref{7648})! */
194 if (pAutoLock)
195 pAutoLock->release();
196
[93444]197 vrc = pVMM->pfnVMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
[70579]198
199 if (pAutoLock)
200 pAutoLock->acquire();
201 }
202
203 AssertRC(vrc);
[93444]204 pVMM->pfnVMR3ReqFree(pReq);
[70579]205
206 return vrc;
207}
208
209
210/**
[70533]211 * Detaches an already attached audio driver from the audio chain.
[70547]212 * Does nothing if the audio driver already is detached or not attached.
[70533]213 *
[70564]214 * @returns VBox status code.
[70533]215 * @param pThis Audio driver to detach.
216 */
217/* static */
[70579]218DECLCALLBACK(int) AudioDriver::detachDriverOnEmt(AudioDriver *pThis)
[70533]219{
220 AssertPtrReturn(pThis, VERR_INVALID_POINTER);
221
[70563]222 if (!pThis->mfAttached) /* Not attached? Bail out. */
223 {
224 LogFunc(("%s: Not attached\n", pThis->mCfg.strName.c_str()));
225 return VINF_SUCCESS;
226 }
227
[70533]228 Console::SafeVMPtrQuiet ptrVM(pThis->mpConsole);
229 Assert(ptrVM.isOk());
230
231 AudioDriverCfg *pCfg = &pThis->mCfg;
232
[70644]233 Assert(pCfg->uLUN != UINT8_MAX);
234
[70544]235 LogFunc(("strName=%s, strDevice=%s, uInst=%u, uLUN=%u\n",
[70644]236 pCfg->strName.c_str(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN));
[70536]237
[70670]238 /* Destroy the entire driver chain for the specified LUN.
239 *
240 * Start with the "AUDIO" driver, as this driver serves as the audio connector between
241 * the device emulation and the select backend(s). */
[94919]242 int vrc = ptrVM.vtable()->pfnPDMR3DriverDetach(ptrVM.rawUVM(), pCfg->strDev.c_str(), pCfg->uInst, pCfg->uLUN,
243 "AUDIO", 0 /* iOccurrence */, 0 /* fFlags */);
244 if (RT_SUCCESS(vrc))
245 vrc = pThis->configure(pCfg->uLUN, false /* Detach */);/** @todo r=bird: Illogical and from what I can tell pointless! */
[70533]246
[94919]247 if (RT_SUCCESS(vrc))
[70533]248 {
[70563]249 pThis->mfAttached = false;
250 LogRel2(("%s: Driver detached\n", pCfg->strName.c_str()));
[70533]251 }
252 else
[94919]253 LogRel(("%s: Failed to detach audio driver, vrc=%Rrc\n", pCfg->strName.c_str(), vrc));
[70533]254
[94919]255 LogFunc(("Returning %Rrc\n", vrc));
256 return vrc;
[70533]257}
258
259/**
260 * Configures the audio driver via CFGM.
261 *
262 * @returns VBox status code.
[70563]263 * @param uLUN LUN to attach driver to.
[70533]264 * @param fAttach Whether to attach or detach the driver configuration to CFGM.
265 *
266 * @thread EMT
267 */
[70563]268int AudioDriver::configure(unsigned uLUN, bool fAttach)
[70533]269{
270 Console::SafeVMPtrQuiet ptrVM(mpConsole);
[93444]271 AssertReturn(ptrVM.isOk(), VERR_INVALID_STATE);
[70533]272
[93444]273 PCFGMNODE pRoot = ptrVM.vtable()->pfnCFGMR3GetRootU(ptrVM.rawUVM());
[70533]274 AssertPtr(pRoot);
[93444]275 PCFGMNODE pDev0 = ptrVM.vtable()->pfnCFGMR3GetChildF(pRoot, "Devices/%s/%u/", mCfg.strDev.c_str(), mCfg.uInst);
[70533]276
[70583]277 if (!pDev0) /* No audio device configured? Bail out. */
[70626]278 {
279 LogRel2(("%s: No audio device configured, skipping to attach driver\n", mCfg.strName.c_str()));
[70583]280 return VINF_SUCCESS;
[70626]281 }
[70583]282
[94919]283 int vrc = VINF_SUCCESS;
[70644]284
[93444]285 PCFGMNODE pDevLun = ptrVM.vtable()->pfnCFGMR3GetChildF(pDev0, "LUN#%u/", uLUN);
[70533]286
287 if (fAttach)
288 {
[93444]289 do /* break "loop" */
[70536]290 {
[94919]291 AssertMsgBreakStmt(pDevLun, ("%s: Device LUN #%u not found\n", mCfg.strName.c_str(), uLUN), vrc = VERR_NOT_FOUND);
[70533]292
[70644]293 LogRel2(("%s: Configuring audio driver (to LUN #%u)\n", mCfg.strName.c_str(), uLUN));
[70533]294
[93444]295 ptrVM.vtable()->pfnCFGMR3RemoveNode(pDevLun); /* Remove LUN completely first. */
[70533]296
[70670]297 /* Insert new LUN configuration and build up the new driver chain. */
[94919]298 vrc = ptrVM.vtable()->pfnCFGMR3InsertNodeF(pDev0, &pDevLun, "LUN#%u/", uLUN); AssertRCBreak(vrc);
299 vrc = ptrVM.vtable()->pfnCFGMR3InsertString(pDevLun, "Driver", "AUDIO"); AssertRCBreak(vrc);
[70670]300
301 PCFGMNODE pLunCfg;
[94919]302 vrc = ptrVM.vtable()->pfnCFGMR3InsertNode(pDevLun, "Config", &pLunCfg); AssertRCBreak(vrc);
[70670]303
[94919]304 vrc = ptrVM.vtable()->pfnCFGMR3InsertStringF(pLunCfg, "DriverName", "%s", mCfg.strName.c_str()); AssertRCBreak(vrc);
305 vrc = ptrVM.vtable()->pfnCFGMR3InsertInteger(pLunCfg, "InputEnabled", mCfg.fEnabledIn); AssertRCBreak(vrc);
306 vrc = ptrVM.vtable()->pfnCFGMR3InsertInteger(pLunCfg, "OutputEnabled", mCfg.fEnabledOut); AssertRCBreak(vrc);
[70533]307
[89580]308 PCFGMNODE pAttachedDriver;
[94919]309 vrc = ptrVM.vtable()->pfnCFGMR3InsertNode(pDevLun, "AttachedDriver", &pAttachedDriver); AssertRCBreak(vrc);
310 vrc = ptrVM.vtable()->pfnCFGMR3InsertStringF(pAttachedDriver, "Driver", "%s", mCfg.strName.c_str()); AssertRCBreak(vrc);
[89580]311 PCFGMNODE pAttachedDriverCfg;
[94919]312 vrc = ptrVM.vtable()->pfnCFGMR3InsertNode(pAttachedDriver, "Config", &pAttachedDriverCfg); AssertRCBreak(vrc);
[70533]313
[89580]314 /* Call the (virtual) method for driver-specific configuration. */
[94919]315 vrc = configureDriver(pAttachedDriverCfg, ptrVM.vtable()); AssertRCBreak(vrc);
[70644]316
317 } while (0);
[70533]318 }
319 else /* Detach */
320 {
[70670]321 LogRel2(("%s: Unconfiguring audio driver\n", mCfg.strName.c_str()));
322 }
[70644]323
[94919]324 if (RT_SUCCESS(vrc))
[89580]325 {
[70670]326#ifdef LOG_ENABLED
[89580]327 LogFunc(("%s: fAttach=%RTbool\n", mCfg.strName.c_str(), fAttach));
[93444]328 ptrVM.vtable()->pfnCFGMR3Dump(pDevLun);
[70670]329#endif
[89580]330 }
331 else
[94919]332 LogRel(("%s: %s audio driver failed with vrc=%Rrc\n", mCfg.strName.c_str(), fAttach ? "Configuring" : "Unconfiguring", vrc));
[70644]333
[94919]334 LogFunc(("Returning %Rrc\n", vrc));
335 return vrc;
[70533]336}
337
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use