VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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