VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/AudioSettingsImpl.cpp@ 95423

Last change on this file since 95423 was 95423, checked in by vboxsync, 3 years ago

Audio/Main: Bigger revamp of the audio interface(s) to later also support host audio device enumeration and selection for individual VMs. The audio settings now live in a dedicated (per-VM) IAudioSettings interface (audio adapter + audio host device stuff), to further tidy up the IMachine interface. Also added stubs for IAudioDevice + IHostAudioDevice, plus enmuerations, left for further implementation. Added a new IHostAudioDeviceChangedEvent that can also be used later by API clients. bugref:10050

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: AudioSettingsImpl.cpp 95423 2022-06-29 11:13:40Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation - Audio settings for a VM.
4 */
5
6/*
7 * Copyright (C) 2022 Oracle Corporation
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#define LOG_GROUP LOG_GROUP_MAIN_AUDIOSETTINGS
19#include "AudioSettingsImpl.h"
20#include "MachineImpl.h"
21
22#include <iprt/cpp/utils.h>
23
24#include <VBox/settings.h>
25
26#include "AutoStateDep.h"
27#include "AutoCaller.h"
28#include "LoggingNew.h"
29
30
31////////////////////////////////////////////////////////////////////////////////
32//
33// AudioSettings private data definition
34//
35////////////////////////////////////////////////////////////////////////////////
36
37struct AudioSettings::Data
38{
39 Data()
40 : pParent(NULL)
41 { }
42
43 Machine * const pParent;
44 const ComObjPtr<AudioAdapter> pAdapter;
45 const ComObjPtr<AudioSettings> pPeer;
46};
47
48DEFINE_EMPTY_CTOR_DTOR(AudioSettings)
49
50HRESULT AudioSettings::FinalConstruct()
51{
52 return BaseFinalConstruct();
53}
54
55void AudioSettings::FinalRelease()
56{
57 uninit();
58 BaseFinalRelease();
59}
60
61
62// public initializer/uninitializer for internal purposes only
63////////////////////////////////////////////////////////////////////////////////
64
65/**
66 * Initializes the audio settings object.
67 *
68 * @param aParent Handle of the parent object.
69 */
70HRESULT AudioSettings::init(Machine *aParent)
71{
72 LogFlowThisFunc(("aParent=%p\n", aParent));
73
74 ComAssertRet(aParent, E_INVALIDARG);
75
76 /* Enclose the state transition NotReady->InInit->Ready */
77 AutoInitSpan autoInitSpan(this);
78 AssertReturn(autoInitSpan.isOk(), E_FAIL);
79
80 m = new Data();
81
82 /* share the parent weakly */
83 unconst(m->pParent) = aParent;
84
85 /* create the audio adapter object (always present, default is disabled) */
86 unconst(m->pAdapter).createObject();
87 m->pAdapter->init(this);
88
89 /* Confirm a successful initialization */
90 autoInitSpan.setSucceeded();
91
92 return S_OK;
93}
94
95/**
96 * Initializes the audio settings object given another audio settings object
97 * (a kind of copy constructor). This object shares data with
98 * the object passed as an argument.
99 *
100 * @note This object must be destroyed before the original object
101 * it shares data with is destroyed.
102 *
103 * @note Locks @a aThat object for reading.
104 */
105HRESULT AudioSettings::init(Machine *aParent, AudioSettings *aThat)
106{
107 LogFlowThisFuncEnter();
108 LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
109
110 ComAssertRet(aParent && aThat, E_INVALIDARG);
111
112 /* Enclose the state transition NotReady->InInit->Ready */
113 AutoInitSpan autoInitSpan(this);
114 AssertReturn(autoInitSpan.isOk(), E_FAIL);
115
116 m = new Data();
117
118 unconst(m->pParent) = aParent;
119 unconst(m->pPeer) = aThat;
120
121 AutoCaller thatCaller(aThat);
122 AssertComRCReturnRC(thatCaller.rc());
123
124 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
125
126 unconst(m->pAdapter) = aThat->m->pAdapter;
127
128 autoInitSpan.setSucceeded();
129
130 LogFlowThisFuncLeave();
131 return S_OK;
132}
133
134/**
135 * Initializes the guest object given another guest object
136 * (a kind of copy constructor). This object makes a private copy of data
137 * of the original object passed as an argument.
138 *
139 * @note Locks @a aThat object for reading.
140 */
141HRESULT AudioSettings::initCopy(Machine *aParent, AudioSettings *aThat)
142{
143 LogFlowThisFuncEnter();
144 LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
145
146 ComAssertRet(aParent && aThat, E_INVALIDARG);
147
148 /* Enclose the state transition NotReady->InInit->Ready */
149 AutoInitSpan autoInitSpan(this);
150 AssertReturn(autoInitSpan.isOk(), E_FAIL);
151
152 m = new Data();
153
154 unconst(m->pParent) = aParent;
155 // pPeer is left null
156
157 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
158
159 HRESULT hr = unconst(m->pAdapter).createObject();
160 ComAssertComRCRet(hr, hr);
161 m->pAdapter->i_copyFrom(aThat->m->pAdapter);
162
163 autoInitSpan.setSucceeded();
164
165 LogFlowThisFuncLeave();
166 return S_OK;
167}
168
169/**
170 * Uninitializes the instance and sets the ready flag to FALSE.
171 * Called either from FinalRelease() or by the parent when it gets destroyed.
172 */
173void AudioSettings::uninit(void)
174{
175 LogFlowThisFunc(("\n"));
176
177 /* Enclose the state transition Ready->InUninit->NotReady */
178 AutoUninitSpan autoUninitSpan(this);
179 if (autoUninitSpan.uninitDone())
180 return;
181
182 delete m;
183 m = NULL;
184}
185
186
187// IAudioSettings properties
188////////////////////////////////////////////////////////////////////////////////
189
190HRESULT AudioSettings::getAdapter(ComPtr<IAudioAdapter> &aAdapter)
191{
192 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
193
194 aAdapter = m->pAdapter;
195
196 return S_OK;
197}
198
199
200// IAudioSettings methods
201////////////////////////////////////////////////////////////////////////////////
202
203HRESULT AudioSettings::getHostAudioDevice(AudioDirection_T aUsage, ComPtr<IHostAudioDevice> &aDevice)
204{
205 RT_NOREF(aUsage, aDevice);
206 ReturnComNotImplemented();
207}
208
209HRESULT AudioSettings::setHostAudioDevice(const ComPtr<IHostAudioDevice> &aDevice, AudioDirection_T aUsage)
210{
211 RT_NOREF(aDevice, aUsage);
212 ReturnComNotImplemented();
213}
214
215
216// public methods only for internal purposes
217////////////////////////////////////////////////////////////////////////////////
218
219/**
220 * Returns the parent object as a weak pointer.
221 */
222Machine* AudioSettings::i_getParent(void)
223{
224 AutoCaller autoCaller(this);
225 AssertComRCReturn(autoCaller.rc(), NULL);
226
227 AssertPtrReturn(m, NULL);
228 return m->pParent;
229}
230
231/**
232 * Determines whether the audio settings currently can be changed or not.
233 *
234 * @returns \c true if the settings can be changed, \c false if not.
235 */
236bool AudioSettings::i_canChangeSettings(void)
237{
238 AutoAnyStateDependency adep(m->pParent);
239 if (FAILED(adep.rc()))
240 return false;
241
242 /** @todo Do some more checks here? */
243 return true;
244}
245
246/**
247 * Gets called when the machine object needs to know that audio adapter settings
248 * have been changed.
249 */
250void AudioSettings::i_onAdapterChanged(IAudioAdapter *pAdapter)
251{
252 LogFlowThisFuncEnter();
253
254 AssertPtrReturnVoid(pAdapter);
255
256 m->pParent->i_onAudioAdapterChange(pAdapter); // mParent is const, needs no locking
257
258 LogFlowThisFuncLeave();
259}
260
261/**
262 * Gets called when the machine object needs to know that a host audio device
263 * has been changed.
264 */
265void AudioSettings::i_onHostDeviceChanged(IHostAudioDevice *pDevice,
266 bool fIsNew, AudioDeviceState_T enmState, IVirtualBoxErrorInfo *pErrInfo)
267{
268 LogFlowThisFuncEnter();
269
270 AssertPtrReturnVoid(pDevice);
271
272 m->pParent->i_onHostAudioDeviceChange(pDevice, fIsNew, enmState, pErrInfo); // mParent is const, needs no locking
273
274 LogFlowThisFuncLeave();
275}
276
277/**
278 * Gets called when the machine object needs to know that the audio settings
279 * have been changed.
280 */
281void AudioSettings::i_onSettingsChanged(void)
282{
283 LogFlowThisFuncEnter();
284
285 AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
286 m->pParent->i_setModified(Machine::IsModified_AudioSettings);
287 mlock.release();
288
289 LogFlowThisFuncLeave();
290}
291
292/**
293 * Loads settings from the given machine node.
294 * May be called once right after this object creation.
295 *
296 * @param data Configuration settings.
297 *
298 * @note Locks this object for writing.
299 */
300HRESULT AudioSettings::i_loadSettings(const settings::AudioAdapter &data)
301{
302 AutoCaller autoCaller(this);
303 AssertComRCReturnRC(autoCaller.rc());
304
305 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
306
307 m->pAdapter->i_loadSettings(data);
308
309 /* Note: The host audio device selection is run-time only, e.g. won't be serialized in the settings! */
310 return S_OK;
311}
312
313/**
314 * Saves settings to the given node.
315 *
316 * @param data Configuration settings.
317 *
318 * @note Locks this object for reading.
319 */
320HRESULT AudioSettings::i_saveSettings(settings::AudioAdapter &data)
321{
322 AutoCaller autoCaller(this);
323 AssertComRCReturnRC(autoCaller.rc());
324
325 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
326
327 m->pAdapter->i_saveSettings(data);
328
329 /* Note: The host audio device selection is run-time only, e.g. won't be serialized in the settings! */
330 return S_OK;
331}
332
333/**
334 * @note Locks this object for writing, together with the peer object
335 * represented by @a aThat (locked for reading).
336 */
337void AudioSettings::i_copyFrom(AudioSettings *aThat)
338{
339 AssertReturnVoid(aThat != NULL);
340
341 /* sanity */
342 AutoCaller autoCaller(this);
343 AssertComRCReturnVoid(autoCaller.rc());
344
345 /* sanity too */
346 AutoCaller thatCaller(aThat);
347 AssertComRCReturnVoid(thatCaller.rc());
348
349 /* peer is not modified, lock it for reading (aThat is "master" so locked
350 * first) */
351 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
352 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
353
354 m->pAdapter->i_copyFrom(aThat->m->pAdapter);
355}
356
357/**
358 * Applies default audio settings, based on the given guest OS type.
359 *
360 * @returns HRESULT
361 * @param aGuestOsType Guest OS type to use for basing the default settings on.
362 */
363HRESULT AudioSettings::i_applyDefaults(ComObjPtr<GuestOSType> &aGuestOsType)
364{
365 AutoCaller autoCaller(this);
366 AssertComRCReturnRC(autoCaller.rc());
367
368 AudioControllerType_T audioController;
369 HRESULT rc = aGuestOsType->COMGETTER(RecommendedAudioController)(&audioController);
370 if (FAILED(rc)) return rc;
371
372 rc = m->pAdapter->COMSETTER(AudioController)(audioController);
373 if (FAILED(rc)) return rc;
374
375 AudioCodecType_T audioCodec;
376 rc = aGuestOsType->COMGETTER(RecommendedAudioCodec)(&audioCodec);
377 if (FAILED(rc)) return rc;
378
379 rc = m->pAdapter->COMSETTER(AudioCodec)(audioCodec);
380 if (FAILED(rc)) return rc;
381
382 rc = m->pAdapter->COMSETTER(Enabled)(true);
383 if (FAILED(rc)) return rc;
384
385 rc = m->pAdapter->COMSETTER(EnabledOut)(true);
386 if (FAILED(rc)) return rc;
387
388 /* Note: We do NOT enable audio input by default due to security reasons!
389 * This always has to be done by the user manually. */
390
391 /* Note: Does not touch the host audio device selection, as this is a run-time only setting. */
392 return S_OK;
393}
394
395/**
396 * @note Locks this object for writing.
397 */
398void AudioSettings::i_rollback(void)
399{
400 /* sanity */
401 AutoCaller autoCaller(this);
402 AssertComRCReturnVoid(autoCaller.rc());
403
404 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
405
406 m->pAdapter->i_rollback();
407
408 /* Note: Does not touch the host audio device selection, as this is a run-time only setting. */
409}
410
411/**
412 * @note Locks this object for writing, together with the peer object (also
413 * for writing) if there is one.
414 */
415void AudioSettings::i_commit(void)
416{
417 /* sanity */
418 AutoCaller autoCaller(this);
419 AssertComRCReturnVoid(autoCaller.rc());
420
421 m->pAdapter->i_commit();
422
423 /* Note: Does not touch the host audio device selection, as this is a run-time only setting. */
424}
425
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette