VirtualBox

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

Last change on this file since 13538 was 8155, checked in by vboxsync, 16 years ago

The Big Sun Rebranding Header Change

  • 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_UNEXPECTED);
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_UNEXPECTED);
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_UNEXPECTED);
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}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use