VirtualBox

source: vbox/trunk/src/VBox/Main/AudioAdapterImpl.cpp@ 26167

Last change on this file since 26167 was 26167, checked in by vboxsync, 15 years ago

Main: get rid of isModified() loops in Machine and subclasses; instead, on every change in machine settings, set dirty bits in Machine

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