VirtualBox

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

Last change on this file since 25414 was 25346, checked in by vboxsync, 14 years ago

iprt/cpputils.h -> iprt/cpp/utils.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
RevLine 
[1]1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
[8155]7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
[1]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
[5999]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.
[8155]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.
[1]20 */
21
22#include "AudioAdapterImpl.h"
23#include "MachineImpl.h"
24#include "Logging.h"
25
[25346]26#include <iprt/cpp/utils.h>
[3348]27
[16560]28#include <VBox/settings.h>
29
[1]30// constructor / destructor
31/////////////////////////////////////////////////////////////////////////////
32
[3348]33DEFINE_EMPTY_CTOR_DTOR (AudioAdapter)
34
[1]35HRESULT AudioAdapter::FinalConstruct()
36{
37 return S_OK;
38}
39
40void AudioAdapter::FinalRelease()
41{
[3348]42 uninit ();
[1]43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
[3348]49 * Initializes the audio adapter object.
[1]50 *
[3348]51 * @param aParent Handle of the parent object.
[1]52 */
[3348]53HRESULT AudioAdapter::init (Machine *aParent)
[1]54{
[21878]55 LogFlowThisFunc(("aParent=%p\n", aParent));
[1]56
[3348]57 ComAssertRet (aParent, E_INVALIDARG);
[1]58
[3348]59 /* Enclose the state transition NotReady->InInit->Ready */
[21878]60 AutoInitSpan autoInitSpan(this);
61 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]62
[20260]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
[21878]74 unconst(mParent) = aParent;
[3348]75 /* mPeer is left null */
[1]76
77 mData.allocate();
[20260]78 mData->mAudioDriver = defaultAudioDriver;
[1]79
[3348]80 /* Confirm a successful initialization */
81 autoInitSpan.setSucceeded();
82
[1]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.
[3348]93 *
94 * @note Locks @a aThat object for reading.
[1]95 */
[3348]96HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
[1]97{
[21878]98 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
[1]99
[3348]100 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]101
[3348]102 /* Enclose the state transition NotReady->InInit->Ready */
[21878]103 AutoInitSpan autoInitSpan(this);
104 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]105
[21878]106 unconst(mParent) = aParent;
107 unconst(mPeer) = aThat;
[1]108
[3348]109 AutoCaller thatCaller (aThat);
[21878]110 AssertComRCReturnRC(thatCaller.rc());
[1]111
[25310]112 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[3348]113 mData.share (aThat->mData);
114
115 /* Confirm a successful initialization */
116 autoInitSpan.setSucceeded();
117
[1]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.
[3348]125 *
126 * @note Locks @a aThat object for reading.
[1]127 */
[3348]128HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
[1]129{
[21878]130 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
[1]131
[3348]132 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]133
[3348]134 /* Enclose the state transition NotReady->InInit->Ready */
[21878]135 AutoInitSpan autoInitSpan(this);
136 AssertReturn(autoInitSpan.isOk(), E_FAIL);
[1]137
[21878]138 unconst(mParent) = aParent;
[3348]139 /* mPeer is left null */
[1]140
[3348]141 AutoCaller thatCaller (aThat);
[21878]142 AssertComRCReturnRC(thatCaller.rc());
[1]143
[25310]144 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[3348]145 mData.attachCopy (aThat->mData);
146
147 /* Confirm a successful initialization */
148 autoInitSpan.setSucceeded();
149
[1]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{
[21878]159 LogFlowThisFunc(("\n"));
[1]160
[3348]161 /* Enclose the state transition Ready->InUninit->NotReady */
[21878]162 AutoUninitSpan autoUninitSpan(this);
[3348]163 if (autoUninitSpan.uninitDone())
164 return;
[1]165
166 mData.free();
167
[21878]168 unconst(mPeer).setNull();
169 unconst(mParent).setNull();
[1]170}
171
172// IAudioAdapter properties
173/////////////////////////////////////////////////////////////////////////////
174
[3348]175STDMETHODIMP AudioAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
[1]176{
[14972]177 CheckComArgOutPointerValid(aEnabled);
[1]178
[21878]179 AutoCaller autoCaller(this);
[25149]180 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]181
[25310]182 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]183
184 *aEnabled = mData->mEnabled;
185
[1]186 return S_OK;
187}
188
[3348]189STDMETHODIMP AudioAdapter::COMSETTER(Enabled)(BOOL aEnabled)
[1]190{
[21878]191 AutoCaller autoCaller(this);
[25149]192 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]193
[3348]194 /* the machine needs to be mutable */
[25149]195 Machine::AutoMutableStateDependency adep(mParent);
196 if (FAILED(adep.rc())) return adep.rc();
[1]197
[25310]198 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]199
200 if (mData->mEnabled != aEnabled)
[1]201 {
202 mData.backup();
[3348]203 mData->mEnabled = aEnabled;
[1]204 }
205
206 return S_OK;
207}
208
[3348]209STDMETHODIMP AudioAdapter::COMGETTER(AudioDriver)(AudioDriverType_T *aAudioDriver)
[1]210{
[14972]211 CheckComArgOutPointerValid(aAudioDriver);
[1]212
[21878]213 AutoCaller autoCaller(this);
[25149]214 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]215
[25310]216 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]217
218 *aAudioDriver = mData->mAudioDriver;
219
[1]220 return S_OK;
221}
222
[3348]223STDMETHODIMP AudioAdapter::COMSETTER(AudioDriver)(AudioDriverType_T aAudioDriver)
[1]224{
[21878]225 AutoCaller autoCaller(this);
[25149]226 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[1]227
[3348]228 /* the machine needs to be mutable */
[25149]229 Machine::AutoMutableStateDependency adep(mParent);
230 if (FAILED(adep.rc())) return adep.rc();
[1]231
[25310]232 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]233
[1]234 HRESULT rc = S_OK;
235
[3348]236 if (mData->mAudioDriver != aAudioDriver)
[1]237 {
238 /*
239 * which audio driver type are we supposed to use?
240 */
[3348]241 switch (aAudioDriver)
[1]242 {
[7207]243 case AudioDriverType_Null:
[3668]244#ifdef RT_OS_WINDOWS
[6056]245# ifdef VBOX_WITH_WINMM
[7466]246 case AudioDriverType_WinMM:
[6056]247# endif
[7466]248 case AudioDriverType_DirectSound:
[3668]249#endif /* RT_OS_WINDOWS */
[7525]250#ifdef RT_OS_SOLARIS
251 case AudioDriverType_SolAudio:
252#endif
[3668]253#ifdef RT_OS_LINUX
[6056]254# ifdef VBOX_WITH_ALSA
[7207]255 case AudioDriverType_ALSA:
[6056]256# endif
257# ifdef VBOX_WITH_PULSE
[7207]258 case AudioDriverType_Pulse:
[6056]259# endif
[3668]260#endif /* RT_OS_LINUX */
[20501]261#if defined (RT_OS_LINUX) || defined (RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
[19058]262 case AudioDriverType_OSS:
263#endif
[3668]264#ifdef RT_OS_DARWIN
[7466]265 case AudioDriverType_CoreAudio:
[7207]266#endif
[3668]267#ifdef RT_OS_OS2
[7207]268 case AudioDriverType_MMPM:
269#endif
[1]270 {
271 mData.backup();
[3348]272 mData->mAudioDriver = aAudioDriver;
[1]273 break;
274 }
[1551]275
[1]276 default:
277 {
[3348]278 AssertMsgFailed (("Wrong audio driver type %d\n",
279 aAudioDriver));
[1]280 rc = E_FAIL;
281 }
282 }
283 }
284
285 return rc;
286}
287
[6597]288STDMETHODIMP AudioAdapter::COMGETTER(AudioController)(AudioControllerType_T *aAudioController)
289{
[14972]290 CheckComArgOutPointerValid(aAudioController);
[6597]291
[21878]292 AutoCaller autoCaller(this);
[25149]293 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[6597]294
[25310]295 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[6597]296
297 *aAudioController = mData->mAudioController;
298
299 return S_OK;
300}
301
302STDMETHODIMP AudioAdapter::COMSETTER(AudioController)(AudioControllerType_T aAudioController)
303{
[21878]304 AutoCaller autoCaller(this);
[25149]305 if (FAILED(autoCaller.rc())) return autoCaller.rc();
[6597]306
307 /* the machine needs to be mutable */
[25149]308 Machine::AutoMutableStateDependency adep(mParent);
309 if (FAILED(adep.rc())) return adep.rc();
[6597]310
[25310]311 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[6597]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
[1]340// IAudioAdapter methods
341/////////////////////////////////////////////////////////////////////////////
342
343// public methods only for internal purposes
344/////////////////////////////////////////////////////////////////////////////
345
[17013]346AudioAdapter::Data::Data()
347{
348 /* Generic defaults */
349 mEnabled = false;
350 mAudioController = AudioControllerType_AC97;
[20260]351 /* Driver defaults to the null audio driver */
[17013]352 mAudioDriver = AudioDriverType_Null;
353}
354
[7207]355/**
[6076]356 * Loads settings from the given machine node.
357 * May be called once right after this object creation.
[7207]358 *
[6076]359 * @param aMachineNode <Machine> node.
[7207]360 *
361 * @note Locks this object for writing.
[6076]362 */
[22173]363HRESULT AudioAdapter::loadSettings(const settings::AudioAdapter &data)
[6076]364{
[21878]365 AutoCaller autoCaller(this);
366 AssertComRCReturnRC(autoCaller.rc());
[6076]367
[25310]368 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[6076]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
[16588]373 * a new AudioAdapter object while all its data fields are in the default
[6076]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
[7207]379 * default to B. */
[6076]380
[22173]381 mData->mEnabled = data.fEnabled;
382 mData->mAudioController = data.controllerType;
383 mData->mAudioDriver = data.driverType;
[6076]384
385 return S_OK;
386}
387
[7207]388/**
[6076]389 * Saves settings to the given machine node.
[7207]390 *
[6076]391 * @param aMachineNode <Machine> node.
[7207]392 *
393 * @note Locks this object for reading.
[6076]394 */
[22173]395HRESULT AudioAdapter::saveSettings(settings::AudioAdapter &data)
[6076]396{
[21878]397 AutoCaller autoCaller(this);
398 AssertComRCReturnRC(autoCaller.rc());
[6076]399
[25310]400 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[6076]401
[22186]402 data.fEnabled = !!mData->mEnabled;
[22173]403 data.controllerType = mData->mAudioController;
404 data.driverType = mData->mAudioDriver;
[6076]405 return S_OK;
406}
407
[7207]408/**
[3348]409 * @note Locks this object for writing.
410 */
411bool AudioAdapter::rollback()
[1]412{
[3348]413 /* sanity */
[21878]414 AutoCaller autoCaller(this);
[3348]415 AssertComRCReturn (autoCaller.rc(), false);
416
[25310]417 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[3348]418
419 bool changed = false;
420
[1]421 if (mData.isBackedUp())
422 {
[3348]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
[7207]432/**
[3348]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 */
[21878]439 AutoCaller autoCaller(this);
[3348]440 AssertComRCReturnVoid (autoCaller.rc());
441
442 /* sanity too */
[7992]443 AutoCaller peerCaller (mPeer);
444 AssertComRCReturnVoid (peerCaller.rc());
[3348]445
[7992]446 /* lock both for writing since we modify both (mPeer is "master" so locked
447 * first) */
[25310]448 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
[3348]449
450 if (mData.isBackedUp())
451 {
[1]452 mData.commit();
453 if (mPeer)
454 {
[3348]455 /* attach new data to the peer and reshare it */
[1]456 mPeer->mData.attach (mData);
457 }
458 }
459}
460
[7207]461/**
[3348]462 * @note Locks this object for writing, together with the peer object
463 * represented by @a aThat (locked for reading).
464 */
[1]465void AudioAdapter::copyFrom (AudioAdapter *aThat)
466{
[3348]467 AssertReturnVoid (aThat != NULL);
[1]468
[3348]469 /* sanity */
[21878]470 AutoCaller autoCaller(this);
[3348]471 AssertComRCReturnVoid (autoCaller.rc());
472
473 /* sanity too */
[7992]474 AutoCaller thatCaller (aThat);
[3348]475 AssertComRCReturnVoid (thatCaller.rc());
476
[7992]477 /* peer is not modified, lock it for reading (aThat is "master" so locked
478 * first) */
[25310]479 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
480 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
[3348]481
482 /* this will back up current data */
[1]483 mData.assignCopy (aThat->mData);
484}
[14772]485/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use