VirtualBox

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

Last change on this file since 94521 was 93444, checked in by vboxsync, 2 years ago

VMM,Main,HostServices: Use a function table for accessing the VBoxVMM.dll/so/dylib functionality, and load it dynamically when the Console object is initialized. Also converted a few drivers in Main to use device helpers to get config values and such. bugref:10074

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

© 2023 Oracle
ContactPrivacy policyTerms of Use