VirtualBox

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

Last change on this file since 49875 was 49875, checked in by vboxsync, 11 years ago

Main: gcc warnings.

  • 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-2013 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->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 AutoMutableStateDependency 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->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->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