VirtualBox

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

Last change on this file since 14949 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 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// constructor / destructor
29/////////////////////////////////////////////////////////////////////////////
30
31DEFINE_EMPTY_CTOR_DTOR (AudioAdapter)
32
33HRESULT AudioAdapter::FinalConstruct()
34{
35 return S_OK;
36}
37
38void AudioAdapter::FinalRelease()
39{
40 uninit ();
41}
42
43// public initializer/uninitializer for internal purposes only
44/////////////////////////////////////////////////////////////////////////////
45
46/**
47 * Initializes the audio adapter object.
48 *
49 * @param aParent Handle of the parent object.
50 */
51HRESULT AudioAdapter::init (Machine *aParent)
52{
53 LogFlowThisFunc (("aParent=%p\n", aParent));
54
55 ComAssertRet (aParent, E_INVALIDARG);
56
57 /* Enclose the state transition NotReady->InInit->Ready */
58 AutoInitSpan autoInitSpan (this);
59 AssertReturn (autoInitSpan.isOk(), E_FAIL);
60
61 unconst (mParent) = aParent;
62 /* mPeer is left null */
63
64 mData.allocate();
65
66 /* Confirm a successful initialization */
67 autoInitSpan.setSucceeded();
68
69 return S_OK;
70}
71
72/**
73 * Initializes the audio adapter object given another audio adapter object
74 * (a kind of copy constructor). This object shares data with
75 * the object passed as an argument.
76 *
77 * @note This object must be destroyed before the original object
78 * it shares data with is destroyed.
79 *
80 * @note Locks @a aThat object for reading.
81 */
82HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
83{
84 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
85
86 ComAssertRet (aParent && aThat, E_INVALIDARG);
87
88 /* Enclose the state transition NotReady->InInit->Ready */
89 AutoInitSpan autoInitSpan (this);
90 AssertReturn (autoInitSpan.isOk(), E_FAIL);
91
92 unconst (mParent) = aParent;
93 unconst (mPeer) = aThat;
94
95 AutoCaller thatCaller (aThat);
96 AssertComRCReturnRC (thatCaller.rc());
97
98 AutoReadLock thatLock (aThat);
99 mData.share (aThat->mData);
100
101 /* Confirm a successful initialization */
102 autoInitSpan.setSucceeded();
103
104 return S_OK;
105}
106
107/**
108 * Initializes the guest object given another guest object
109 * (a kind of copy constructor). This object makes a private copy of data
110 * of the original object passed as an argument.
111 *
112 * @note Locks @a aThat object for reading.
113 */
114HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
115{
116 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
117
118 ComAssertRet (aParent && aThat, E_INVALIDARG);
119
120 /* Enclose the state transition NotReady->InInit->Ready */
121 AutoInitSpan autoInitSpan (this);
122 AssertReturn (autoInitSpan.isOk(), E_FAIL);
123
124 unconst (mParent) = aParent;
125 /* mPeer is left null */
126
127 AutoCaller thatCaller (aThat);
128 AssertComRCReturnRC (thatCaller.rc());
129
130 AutoReadLock thatLock (aThat);
131 mData.attachCopy (aThat->mData);
132
133 /* Confirm a successful initialization */
134 autoInitSpan.setSucceeded();
135
136 return S_OK;
137}
138
139/**
140 * Uninitializes the instance and sets the ready flag to FALSE.
141 * Called either from FinalRelease() or by the parent when it gets destroyed.
142 */
143void AudioAdapter::uninit()
144{
145 LogFlowThisFunc (("\n"));
146
147 /* Enclose the state transition Ready->InUninit->NotReady */
148 AutoUninitSpan autoUninitSpan (this);
149 if (autoUninitSpan.uninitDone())
150 return;
151
152 mData.free();
153
154 unconst (mPeer).setNull();
155 unconst (mParent).setNull();
156}
157
158// IAudioAdapter properties
159/////////////////////////////////////////////////////////////////////////////
160
161STDMETHODIMP AudioAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
162{
163 if (!aEnabled)
164 return E_POINTER;
165
166 AutoCaller autoCaller (this);
167 CheckComRCReturnRC (autoCaller.rc());
168
169 AutoReadLock alock (this);
170
171 *aEnabled = mData->mEnabled;
172
173 return S_OK;
174}
175
176STDMETHODIMP AudioAdapter::COMSETTER(Enabled)(BOOL aEnabled)
177{
178 AutoCaller autoCaller (this);
179 CheckComRCReturnRC (autoCaller.rc());
180
181 /* the machine needs to be mutable */
182 Machine::AutoMutableStateDependency adep (mParent);
183 CheckComRCReturnRC (adep.rc());
184
185 AutoWriteLock alock (this);
186
187 if (mData->mEnabled != aEnabled)
188 {
189 mData.backup();
190 mData->mEnabled = aEnabled;
191 }
192
193 return S_OK;
194}
195
196STDMETHODIMP AudioAdapter::COMGETTER(AudioDriver)(AudioDriverType_T *aAudioDriver)
197{
198 if (!aAudioDriver)
199 return E_POINTER;
200
201 AutoCaller autoCaller (this);
202 CheckComRCReturnRC (autoCaller.rc());
203
204 AutoReadLock alock (this);
205
206 *aAudioDriver = mData->mAudioDriver;
207
208 return S_OK;
209}
210
211STDMETHODIMP AudioAdapter::COMSETTER(AudioDriver)(AudioDriverType_T aAudioDriver)
212{
213 AutoCaller autoCaller (this);
214 CheckComRCReturnRC (autoCaller.rc());
215
216 /* the machine needs to be mutable */
217 Machine::AutoMutableStateDependency adep (mParent);
218 CheckComRCReturnRC (adep.rc());
219
220 AutoWriteLock alock (this);
221
222 HRESULT rc = S_OK;
223
224 if (mData->mAudioDriver != aAudioDriver)
225 {
226 /*
227 * which audio driver type are we supposed to use?
228 */
229 switch (aAudioDriver)
230 {
231 case AudioDriverType_Null:
232#ifdef RT_OS_WINDOWS
233# ifdef VBOX_WITH_WINMM
234 case AudioDriverType_WinMM:
235# endif
236 case AudioDriverType_DirectSound:
237#endif /* RT_OS_WINDOWS */
238#ifdef RT_OS_SOLARIS
239 case AudioDriverType_SolAudio:
240#endif
241#ifdef RT_OS_LINUX
242 case AudioDriverType_OSS:
243# ifdef VBOX_WITH_ALSA
244 case AudioDriverType_ALSA:
245# endif
246# ifdef VBOX_WITH_PULSE
247 case AudioDriverType_Pulse:
248# endif
249#endif /* RT_OS_LINUX */
250#ifdef RT_OS_DARWIN
251 case AudioDriverType_CoreAudio:
252#endif
253#ifdef RT_OS_OS2
254 case AudioDriverType_MMPM:
255#endif
256 {
257 mData.backup();
258 mData->mAudioDriver = aAudioDriver;
259 break;
260 }
261
262 default:
263 {
264 AssertMsgFailed (("Wrong audio driver type %d\n",
265 aAudioDriver));
266 rc = E_FAIL;
267 }
268 }
269 }
270
271 return rc;
272}
273
274STDMETHODIMP AudioAdapter::COMGETTER(AudioController)(AudioControllerType_T *aAudioController)
275{
276 if (!aAudioController)
277 return E_POINTER;
278
279 AutoCaller autoCaller (this);
280 CheckComRCReturnRC (autoCaller.rc());
281
282 AutoReadLock alock (this);
283
284 *aAudioController = mData->mAudioController;
285
286 return S_OK;
287}
288
289STDMETHODIMP AudioAdapter::COMSETTER(AudioController)(AudioControllerType_T aAudioController)
290{
291 AutoCaller autoCaller (this);
292 CheckComRCReturnRC (autoCaller.rc());
293
294 /* the machine needs to be mutable */
295 Machine::AutoMutableStateDependency adep (mParent);
296 CheckComRCReturnRC (adep.rc());
297
298 AutoWriteLock alock (this);
299
300 HRESULT rc = S_OK;
301
302 if (mData->mAudioController != aAudioController)
303 {
304 /*
305 * which audio hardware type are we supposed to use?
306 */
307 switch (aAudioController)
308 {
309 case AudioControllerType_AC97:
310 case AudioControllerType_SB16:
311 mData.backup();
312 mData->mAudioController = aAudioController;
313 break;
314
315 default:
316 {
317 AssertMsgFailed (("Wrong audio controller type %d\n",
318 aAudioController));
319 rc = E_FAIL;
320 }
321 }
322 }
323
324 return rc;
325}
326
327// IAudioAdapter methods
328/////////////////////////////////////////////////////////////////////////////
329
330// public methods only for internal purposes
331/////////////////////////////////////////////////////////////////////////////
332
333/**
334 * Loads settings from the given machine node.
335 * May be called once right after this object creation.
336 *
337 * @param aMachineNode <Machine> node.
338 *
339 * @note Locks this object for writing.
340 */
341HRESULT AudioAdapter::loadSettings (const settings::Key &aMachineNode)
342{
343 using namespace settings;
344
345 AssertReturn (!aMachineNode.isNull(), E_FAIL);
346
347 AutoCaller autoCaller (this);
348 AssertComRCReturnRC (autoCaller.rc());
349
350 AutoWriteLock alock (this);
351
352 /* Note: we assume that the default values for attributes of optional
353 * nodes are assigned in the Data::Data() constructor and don't do it
354 * here. It implies that this method may only be called after constructing
355 * a new BIOSSettings object while all its data fields are in the default
356 * values. Exceptions are fields whose creation time defaults don't match
357 * values that should be applied when these fields are not explicitly set
358 * in the settings file (for backwards compatibility reasons). This takes
359 * place when a setting of a newly created object must default to A while
360 * the same setting of an object loaded from the old settings file must
361 * default to B. */
362
363 /* AudioAdapter node (required) */
364 Key audioAdapterNode = aMachineNode.key ("AudioAdapter");
365
366 /* is the adapter enabled? (required) */
367 mData->mEnabled = audioAdapterNode.value <bool> ("enabled");
368
369 /* now check the audio adapter (not required, default is AC97) */
370 const char *controller = audioAdapterNode.stringValue ("controller");
371 if (strcmp (controller, "SB16") == 0)
372 mData->mAudioController = AudioControllerType_SB16;
373 else
374 mData->mAudioController = AudioControllerType_AC97;
375
376 /* now check the audio driver (required) */
377 const char *driver = audioAdapterNode.stringValue ("driver");
378 mData->mAudioDriver = AudioDriverType_Null;
379 if (strcmp (driver, "Null") == 0)
380 ; /* Null has been set above */
381#ifdef RT_OS_WINDOWS
382 else if (strcmp (driver, "WinMM") == 0)
383#ifdef VBOX_WITH_WINMM
384 mData->mAudioDriver = AudioDriverType_WinMM;
385#else
386 /* fall back to dsound */
387 mData->mAudioDriver = AudioDriverType_DirectSound;
388#endif
389 else if (strcmp (driver, "DirectSound") == 0)
390 mData->mAudioDriver = AudioDriverType_DirectSound;
391#endif // RT_OS_WINDOWS
392#ifdef RT_OS_SOLARIS
393 else if (strcmp (driver, "SolAudio") == 0)
394 mData->mAudioDriver = AudioDriverType_SolAudio;
395#endif // RT_OS_SOLARIS
396#ifdef RT_OS_LINUX
397 else if (strcmp (driver, "OSS") == 0)
398 mData->mAudioDriver = AudioDriverType_OSS;
399 else if (strcmp (driver, "ALSA") == 0)
400# ifdef VBOX_WITH_ALSA
401 mData->mAudioDriver = AudioDriverType_ALSA;
402# else
403 /* fall back to OSS */
404 mData->mAudioDriver = AudioDriverType_OSS;
405# endif
406 else if (strcmp (driver, "Pulse") == 0)
407# ifdef VBOX_WITH_PULSE
408 mData->mAudioDriver = AudioDriverType_Pulse;
409# else
410 /* fall back to OSS */
411 mData->mAudioDriver = AudioDriverType_OSS;
412# endif
413#endif // RT_OS_LINUX
414#ifdef RT_OS_DARWIN
415 else if (strcmp (driver, "CoreAudio") == 0)
416 mData->mAudioDriver = AudioDriverType_CoreAudio;
417#endif
418#ifdef RT_OS_OS2
419 else if (strcmp (driver, "MMPM") == 0)
420 mData->mAudioDriver = AudioDriverType_MMPM;
421#endif
422 else
423 AssertMsgFailed (("Invalid driver '%s'\n", driver));
424
425 return S_OK;
426}
427
428/**
429 * Saves settings to the given machine node.
430 *
431 * @param aMachineNode <Machine> node.
432 *
433 * @note Locks this object for reading.
434 */
435HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode)
436{
437 using namespace settings;
438
439 AssertReturn (!aMachineNode.isNull(), E_FAIL);
440
441 AutoCaller autoCaller (this);
442 AssertComRCReturnRC (autoCaller.rc());
443
444 AutoReadLock alock (this);
445
446 Key node = aMachineNode.createKey ("AudioAdapter");
447
448 const char *controllerStr = NULL;
449 switch (mData->mAudioController)
450 {
451 case AudioControllerType_SB16:
452 {
453 controllerStr = "SB16";
454 break;
455 }
456 default:
457 {
458 controllerStr = "AC97";
459 break;
460 }
461 }
462 node.setStringValue ("controller", controllerStr);
463
464 const char *driverStr = NULL;
465 switch (mData->mAudioDriver)
466 {
467 case AudioDriverType_Null:
468 {
469 driverStr = "Null";
470 break;
471 }
472#ifdef RT_OS_WINDOWS
473 case AudioDriverType_WinMM:
474# ifdef VBOX_WITH_WINMM
475 {
476 driverStr = "WinMM";
477 break;
478 }
479# endif
480 case AudioDriverType_DirectSound:
481 {
482 driverStr = "DirectSound";
483 break;
484 }
485#endif /* RT_OS_WINDOWS */
486#ifdef RT_OS_SOLARIS
487 case AudioDriverType_SolAudio:
488 {
489 driverStr = "SolAudio";
490 break;
491 }
492#endif
493#ifdef RT_OS_LINUX
494 case AudioDriverType_ALSA:
495# ifdef VBOX_WITH_ALSA
496 {
497 driverStr = "ALSA";
498 break;
499 }
500# endif
501 case AudioDriverType_Pulse:
502# ifdef VBOX_WITH_PULSE
503 {
504 driverStr = "Pulse";
505 break;
506 }
507# endif
508 case AudioDriverType_OSS:
509 {
510 driverStr = "OSS";
511 break;
512 }
513#endif /* RT_OS_LINUX */
514#ifdef RT_OS_DARWIN
515 case AudioDriverType_CoreAudio:
516 {
517 driverStr = "CoreAudio";
518 break;
519 }
520#endif
521#ifdef RT_OS_OS2
522 case AudioDriverType_MMPM:
523 {
524 driverStr = "MMPM";
525 break;
526 }
527#endif
528 default:
529 ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d\n",
530 mData->mAudioDriver),
531 E_FAIL);
532 }
533 node.setStringValue ("driver", driverStr);
534
535 node.setValue <bool> ("enabled", !!mData->mEnabled);
536
537 return S_OK;
538}
539
540/**
541 * @note Locks this object for writing.
542 */
543bool AudioAdapter::rollback()
544{
545 /* sanity */
546 AutoCaller autoCaller (this);
547 AssertComRCReturn (autoCaller.rc(), false);
548
549 AutoWriteLock alock (this);
550
551 bool changed = false;
552
553 if (mData.isBackedUp())
554 {
555 /* we need to check all data to see whether anything will be changed
556 * after rollback */
557 changed = mData.hasActualChanges();
558 mData.rollback();
559 }
560
561 return changed;
562}
563
564/**
565 * @note Locks this object for writing, together with the peer object (also
566 * for writing) if there is one.
567 */
568void AudioAdapter::commit()
569{
570 /* sanity */
571 AutoCaller autoCaller (this);
572 AssertComRCReturnVoid (autoCaller.rc());
573
574 /* sanity too */
575 AutoCaller peerCaller (mPeer);
576 AssertComRCReturnVoid (peerCaller.rc());
577
578 /* lock both for writing since we modify both (mPeer is "master" so locked
579 * first) */
580 AutoMultiWriteLock2 alock (mPeer, this);
581
582 if (mData.isBackedUp())
583 {
584 mData.commit();
585 if (mPeer)
586 {
587 /* attach new data to the peer and reshare it */
588 mPeer->mData.attach (mData);
589 }
590 }
591}
592
593/**
594 * @note Locks this object for writing, together with the peer object
595 * represented by @a aThat (locked for reading).
596 */
597void AudioAdapter::copyFrom (AudioAdapter *aThat)
598{
599 AssertReturnVoid (aThat != NULL);
600
601 /* sanity */
602 AutoCaller autoCaller (this);
603 AssertComRCReturnVoid (autoCaller.rc());
604
605 /* sanity too */
606 AutoCaller thatCaller (aThat);
607 AssertComRCReturnVoid (thatCaller.rc());
608
609 /* peer is not modified, lock it for reading (aThat is "master" so locked
610 * first) */
611 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
612
613 /* this will back up current data */
614 mData.assignCopy (aThat->mData);
615}
616/* 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