VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/AudioAdapterImpl.cpp@ 54971

Last change on this file since 54971 was 54971, checked in by vboxsync, 10 years ago

Main/AudioAdapter+BandwidthControl+Machine+NetworkAdapter+ParallelPort+SerialPort+StorageController+USBDeviceFilter+USBDeviceFilters: Adjust rules when settings can be changed to allow as much as possible. Some changes restored the old rules (a previous change made the definition more restrictive), but many now allow changing settings when VM is saved or even at runtime when it is safe. Will resolve many complaints, especially when the GUI also is adapted accordingly.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2015 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#include "AudioAdapterImpl.h"
19#include "MachineImpl.h"
20
21#include <iprt/cpp/utils.h>
22
23#include <VBox/settings.h>
24
25#include "AutoStateDep.h"
26#include "AutoCaller.h"
27#include "Logging.h"
28
29struct AudioAdapterData
30{
31 AudioAdapterData() :
32 mEnabled(false),
33 mAudioDriver(AudioDriverType_Null),
34 mAudioController(AudioControllerType_AC97)
35 {}
36
37 BOOL mEnabled;
38 AudioDriverType_T mAudioDriver;
39 AudioControllerType_T mAudioController;
40};
41
42struct AudioAdapter::Data
43{
44 Backupable<AudioAdapterData> m;
45};
46
47// constructor / destructor
48/////////////////////////////////////////////////////////////////////////////
49
50AudioAdapter::AudioAdapter()
51 : mParent(NULL),
52 mData(NULL)
53{
54}
55
56AudioAdapter::~AudioAdapter()
57{
58}
59
60HRESULT AudioAdapter::FinalConstruct()
61{
62 return BaseFinalConstruct();
63}
64
65void AudioAdapter::FinalRelease()
66{
67 uninit();
68 BaseFinalRelease();
69}
70
71// public initializer/uninitializer for internal purposes only
72/////////////////////////////////////////////////////////////////////////////
73
74/**
75 * Initializes the audio adapter object.
76 *
77 * @param aParent Handle of the parent object.
78 */
79HRESULT AudioAdapter::init (Machine *aParent)
80{
81 LogFlowThisFunc(("aParent=%p\n", aParent));
82
83 ComAssertRet(aParent, E_INVALIDARG);
84
85 /* Enclose the state transition NotReady->InInit->Ready */
86 AutoInitSpan autoInitSpan(this);
87 AssertReturn(autoInitSpan.isOk(), E_FAIL);
88
89 /* Get the default audio driver out of the system properties */
90 ComPtr<IVirtualBox> VBox;
91 HRESULT rc = aParent->COMGETTER(Parent)(VBox.asOutParam());
92 if (FAILED(rc)) return rc;
93 ComPtr<ISystemProperties> sysProps;
94 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
95 if (FAILED(rc)) return rc;
96 AudioDriverType_T defaultAudioDriver;
97 rc = sysProps->COMGETTER(DefaultAudioDriver)(&defaultAudioDriver);
98 if (FAILED(rc)) return rc;
99
100 unconst(mParent) = aParent;
101 /* mPeer is left null */
102
103 mData = new Data();
104 mData->m.allocate();
105 mData->m->mAudioDriver = defaultAudioDriver;
106
107 /* Confirm a successful initialization */
108 autoInitSpan.setSucceeded();
109
110 return S_OK;
111}
112
113/**
114 * Initializes the audio adapter object given another audio adapter object
115 * (a kind of copy constructor). This object shares data with
116 * the object passed as an argument.
117 *
118 * @note This object must be destroyed before the original object
119 * it shares data with is destroyed.
120 *
121 * @note Locks @a aThat object for reading.
122 */
123HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
124{
125 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
126
127 ComAssertRet(aParent && aThat, E_INVALIDARG);
128
129 /* Enclose the state transition NotReady->InInit->Ready */
130 AutoInitSpan autoInitSpan(this);
131 AssertReturn(autoInitSpan.isOk(), E_FAIL);
132
133 unconst(mParent) = aParent;
134 unconst(mPeer) = aThat;
135
136 AutoCaller thatCaller (aThat);
137 AssertComRCReturnRC(thatCaller.rc());
138
139 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
140 mData = new Data();
141 mData->m.share (aThat->mData->m);
142
143 /* Confirm a successful initialization */
144 autoInitSpan.setSucceeded();
145
146 return S_OK;
147}
148
149/**
150 * Initializes the guest object given another guest object
151 * (a kind of copy constructor). This object makes a private copy of data
152 * of the original object passed as an argument.
153 *
154 * @note Locks @a aThat object for reading.
155 */
156HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
157{
158 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
159
160 ComAssertRet(aParent && aThat, E_INVALIDARG);
161
162 /* Enclose the state transition NotReady->InInit->Ready */
163 AutoInitSpan autoInitSpan(this);
164 AssertReturn(autoInitSpan.isOk(), E_FAIL);
165
166 unconst(mParent) = aParent;
167 /* mPeer is left null */
168
169 AutoCaller thatCaller (aThat);
170 AssertComRCReturnRC(thatCaller.rc());
171
172 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
173 mData = new Data();
174 mData->m.attachCopy (aThat->mData->m);
175
176 /* Confirm a successful initialization */
177 autoInitSpan.setSucceeded();
178
179 return S_OK;
180}
181
182/**
183 * Uninitializes the instance and sets the ready flag to FALSE.
184 * Called either from FinalRelease() or by the parent when it gets destroyed.
185 */
186void AudioAdapter::uninit()
187{
188 LogFlowThisFunc(("\n"));
189
190 /* Enclose the state transition Ready->InUninit->NotReady */
191 AutoUninitSpan autoUninitSpan(this);
192 if (autoUninitSpan.uninitDone())
193 return;
194
195 mData->m.free();
196 delete mData;
197 mData = NULL;
198
199 unconst(mPeer) = NULL;
200 unconst(mParent) = NULL;
201}
202
203// IAudioAdapter properties
204/////////////////////////////////////////////////////////////////////////////
205
206HRESULT AudioAdapter::getEnabled(BOOL *aEnabled)
207{
208 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
209
210 *aEnabled = mData->m->mEnabled;
211
212 return S_OK;
213}
214
215HRESULT AudioAdapter::setEnabled(BOOL aEnabled)
216{
217 /* the machine needs to be mutable */
218 AutoMutableStateDependency adep(mParent);
219 if (FAILED(adep.rc())) return adep.rc();
220
221 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
222
223 if (mData->m->mEnabled != aEnabled)
224 {
225 mData->m.backup();
226 mData->m->mEnabled = aEnabled;
227
228 alock.release();
229 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
230 mParent->i_setModified(Machine::IsModified_AudioAdapter);
231 }
232
233 return S_OK;
234}
235
236HRESULT AudioAdapter::getAudioDriver(AudioDriverType_T *aAudioDriver)
237{
238 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
239
240 *aAudioDriver = mData->m->mAudioDriver;
241
242 return S_OK;
243}
244
245HRESULT AudioAdapter::setAudioDriver(AudioDriverType_T aAudioDriver)
246{
247
248 /* the machine needs to be mutable */
249 AutoMutableOrSavedStateDependency adep(mParent);
250 if (FAILED(adep.rc())) return adep.rc();
251
252 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
253
254 HRESULT rc = S_OK;
255
256 if (mData->m->mAudioDriver != aAudioDriver)
257 {
258 if (settings::MachineConfigFile::isAudioDriverAllowedOnThisHost(aAudioDriver))
259 {
260 mData->m.backup();
261 mData->m->mAudioDriver = aAudioDriver;
262 alock.release();
263 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
264 mParent->i_setModified(Machine::IsModified_AudioAdapter);
265 }
266 else
267 {
268 AssertMsgFailed(("Wrong audio driver type %d\n", aAudioDriver));
269 rc = E_FAIL;
270 }
271 }
272
273 return rc;
274}
275
276HRESULT AudioAdapter::getAudioController(AudioControllerType_T *aAudioController)
277{
278 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
279
280 *aAudioController = mData->m->mAudioController;
281
282 return S_OK;
283}
284
285HRESULT AudioAdapter::setAudioController(AudioControllerType_T aAudioController)
286{
287 /* the machine needs to be mutable */
288 AutoMutableStateDependency adep(mParent);
289 if (FAILED(adep.rc())) return adep.rc();
290
291 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
292
293 HRESULT rc = S_OK;
294
295 if (mData->m->mAudioController != aAudioController)
296 {
297 /*
298 * which audio hardware type are we supposed to use?
299 */
300 switch (aAudioController)
301 {
302 case AudioControllerType_AC97:
303 case AudioControllerType_SB16:
304 case AudioControllerType_HDA:
305 {
306 mData->m.backup();
307 mData->m->mAudioController = aAudioController;
308 alock.release();
309 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
310 mParent->i_setModified(Machine::IsModified_AudioAdapter);
311 break;
312 }
313
314 default:
315 AssertMsgFailed (("Wrong audio controller type %d\n",
316 aAudioController));
317 rc = E_FAIL;
318 }
319 }
320
321 return rc;
322}
323
324// IAudioAdapter methods
325/////////////////////////////////////////////////////////////////////////////
326
327// public methods only for internal purposes
328/////////////////////////////////////////////////////////////////////////////
329
330/**
331 * Loads settings from the given machine node.
332 * May be called once right after this object creation.
333 *
334 * @param aMachineNode <Machine> node.
335 *
336 * @note Locks this object for writing.
337 */
338HRESULT AudioAdapter::i_loadSettings(const settings::AudioAdapter &data)
339{
340 AutoCaller autoCaller(this);
341 AssertComRCReturnRC(autoCaller.rc());
342
343 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
344
345 /* Note: we assume that the default values for attributes of optional
346 * nodes are assigned in the Data::Data() constructor and don't do it
347 * here. It implies that this method may only be called after constructing
348 * a new AudioAdapter object while all its data fields are in the default
349 * values. Exceptions are fields whose creation time defaults don't match
350 * values that should be applied when these fields are not explicitly set
351 * in the settings file (for backwards compatibility reasons). This takes
352 * place when a setting of a newly created object must default to A while
353 * the same setting of an object loaded from the old settings file must
354 * default to B. */
355
356 mData->m->mEnabled = data.fEnabled;
357 mData->m->mAudioController = data.controllerType;
358 mData->m->mAudioDriver = data.driverType;
359
360 return S_OK;
361}
362
363/**
364 * Saves settings to the given machine node.
365 *
366 * @param aMachineNode <Machine> node.
367 *
368 * @note Locks this object for reading.
369 */
370HRESULT AudioAdapter::i_saveSettings(settings::AudioAdapter &data)
371{
372 AutoCaller autoCaller(this);
373 AssertComRCReturnRC(autoCaller.rc());
374
375 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
376
377 data.fEnabled = !!mData->m->mEnabled;
378 data.controllerType = mData->m->mAudioController;
379 data.driverType = mData->m->mAudioDriver;
380 return S_OK;
381}
382
383/**
384 * @note Locks this object for writing.
385 */
386void AudioAdapter::i_rollback()
387{
388 /* sanity */
389 AutoCaller autoCaller(this);
390 AssertComRCReturnVoid(autoCaller.rc());
391
392 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
393
394 mData->m.rollback();
395}
396
397/**
398 * @note Locks this object for writing, together with the peer object (also
399 * for writing) if there is one.
400 */
401void AudioAdapter::i_commit()
402{
403 /* sanity */
404 AutoCaller autoCaller(this);
405 AssertComRCReturnVoid (autoCaller.rc());
406
407 /* sanity too */
408 AutoCaller peerCaller (mPeer);
409 AssertComRCReturnVoid (peerCaller.rc());
410
411 /* lock both for writing since we modify both (mPeer is "master" so locked
412 * first) */
413 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
414
415 if (mData->m.isBackedUp())
416 {
417 mData->m.commit();
418 if (mPeer)
419 {
420 /* attach new data to the peer and reshare it */
421 mPeer->mData->m.attach (mData->m);
422 }
423 }
424}
425
426/**
427 * @note Locks this object for writing, together with the peer object
428 * represented by @a aThat (locked for reading).
429 */
430void AudioAdapter::i_copyFrom(AudioAdapter *aThat)
431{
432 AssertReturnVoid (aThat != NULL);
433
434 /* sanity */
435 AutoCaller autoCaller(this);
436 AssertComRCReturnVoid (autoCaller.rc());
437
438 /* sanity too */
439 AutoCaller thatCaller (aThat);
440 AssertComRCReturnVoid (thatCaller.rc());
441
442 /* peer is not modified, lock it for reading (aThat is "master" so locked
443 * first) */
444 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
445 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
446
447 /* this will back up current data */
448 mData->m.assignCopy(aThat->mData->m);
449}
450/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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