VirtualBox

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

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

Main: cleanup: get rid of VirtualBoxBaseProto, move AutoCaller*/*Span* classes out of VirtualBoxBaseProto class scope and into separate header; move CombinedProgress into separate header (it's only used by Console any more)

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