VirtualBox

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

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

Main: cleanup: remove all CheckComRC* macros (no functional change)

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