VirtualBox

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

Last change on this file since 43978 was 35638, checked in by vboxsync, 14 years ago

Main. QT/FE: fix long standing COM issue

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