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
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
[3348]26#include <iprt/cpputils.h>
27
[1]28// constructor / destructor
29/////////////////////////////////////////////////////////////////////////////
30
[3348]31DEFINE_EMPTY_CTOR_DTOR (AudioAdapter)
32
[1]33HRESULT AudioAdapter::FinalConstruct()
34{
35 return S_OK;
36}
37
38void AudioAdapter::FinalRelease()
39{
[3348]40 uninit ();
[1]41}
42
43// public initializer/uninitializer for internal purposes only
44/////////////////////////////////////////////////////////////////////////////
45
46/**
[3348]47 * Initializes the audio adapter object.
[1]48 *
[3348]49 * @param aParent Handle of the parent object.
[1]50 */
[3348]51HRESULT AudioAdapter::init (Machine *aParent)
[1]52{
[3348]53 LogFlowThisFunc (("aParent=%p\n", aParent));
[1]54
[3348]55 ComAssertRet (aParent, E_INVALIDARG);
[1]56
[3348]57 /* Enclose the state transition NotReady->InInit->Ready */
58 AutoInitSpan autoInitSpan (this);
59 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]60
[3348]61 unconst (mParent) = aParent;
62 /* mPeer is left null */
[1]63
64 mData.allocate();
65
[3348]66 /* Confirm a successful initialization */
67 autoInitSpan.setSucceeded();
68
[1]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.
[3348]79 *
80 * @note Locks @a aThat object for reading.
[1]81 */
[3348]82HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
[1]83{
[3348]84 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
[1]85
[3348]86 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]87
[3348]88 /* Enclose the state transition NotReady->InInit->Ready */
89 AutoInitSpan autoInitSpan (this);
90 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]91
[3348]92 unconst (mParent) = aParent;
93 unconst (mPeer) = aThat;
[1]94
[3348]95 AutoCaller thatCaller (aThat);
96 AssertComRCReturnRC (thatCaller.rc());
[1]97
[8083]98 AutoReadLock thatLock (aThat);
[3348]99 mData.share (aThat->mData);
100
101 /* Confirm a successful initialization */
102 autoInitSpan.setSucceeded();
103
[1]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.
[3348]111 *
112 * @note Locks @a aThat object for reading.
[1]113 */
[3348]114HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
[1]115{
[3348]116 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
[1]117
[3348]118 ComAssertRet (aParent && aThat, E_INVALIDARG);
[1]119
[3348]120 /* Enclose the state transition NotReady->InInit->Ready */
121 AutoInitSpan autoInitSpan (this);
122 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]123
[3348]124 unconst (mParent) = aParent;
125 /* mPeer is left null */
[1]126
[3348]127 AutoCaller thatCaller (aThat);
128 AssertComRCReturnRC (thatCaller.rc());
[1]129
[8083]130 AutoReadLock thatLock (aThat);
[3348]131 mData.attachCopy (aThat->mData);
132
133 /* Confirm a successful initialization */
134 autoInitSpan.setSucceeded();
135
[1]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{
[3348]145 LogFlowThisFunc (("\n"));
[1]146
[3348]147 /* Enclose the state transition Ready->InUninit->NotReady */
148 AutoUninitSpan autoUninitSpan (this);
149 if (autoUninitSpan.uninitDone())
150 return;
[1]151
152 mData.free();
153
[3348]154 unconst (mPeer).setNull();
155 unconst (mParent).setNull();
[1]156}
157
158// IAudioAdapter properties
159/////////////////////////////////////////////////////////////////////////////
160
[3348]161STDMETHODIMP AudioAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
[1]162{
[3348]163 if (!aEnabled)
[1]164 return E_POINTER;
165
[3348]166 AutoCaller autoCaller (this);
167 CheckComRCReturnRC (autoCaller.rc());
[1]168
[8083]169 AutoReadLock alock (this);
[3348]170
171 *aEnabled = mData->mEnabled;
172
[1]173 return S_OK;
174}
175
[3348]176STDMETHODIMP AudioAdapter::COMSETTER(Enabled)(BOOL aEnabled)
[1]177{
[3348]178 AutoCaller autoCaller (this);
179 CheckComRCReturnRC (autoCaller.rc());
[1]180
[3348]181 /* the machine needs to be mutable */
182 Machine::AutoMutableStateDependency adep (mParent);
183 CheckComRCReturnRC (adep.rc());
[1]184
[8083]185 AutoWriteLock alock (this);
[3348]186
187 if (mData->mEnabled != aEnabled)
[1]188 {
189 mData.backup();
[3348]190 mData->mEnabled = aEnabled;
[1]191 }
192
193 return S_OK;
194}
195
[3348]196STDMETHODIMP AudioAdapter::COMGETTER(AudioDriver)(AudioDriverType_T *aAudioDriver)
[1]197{
[3348]198 if (!aAudioDriver)
[1]199 return E_POINTER;
200
[3348]201 AutoCaller autoCaller (this);
202 CheckComRCReturnRC (autoCaller.rc());
[1]203
[8083]204 AutoReadLock alock (this);
[3348]205
206 *aAudioDriver = mData->mAudioDriver;
207
[1]208 return S_OK;
209}
210
[3348]211STDMETHODIMP AudioAdapter::COMSETTER(AudioDriver)(AudioDriverType_T aAudioDriver)
[1]212{
[3348]213 AutoCaller autoCaller (this);
214 CheckComRCReturnRC (autoCaller.rc());
[1]215
[3348]216 /* the machine needs to be mutable */
217 Machine::AutoMutableStateDependency adep (mParent);
218 CheckComRCReturnRC (adep.rc());
[1]219
[8083]220 AutoWriteLock alock (this);
[3348]221
[1]222 HRESULT rc = S_OK;
223
[3348]224 if (mData->mAudioDriver != aAudioDriver)
[1]225 {
226 /*
227 * which audio driver type are we supposed to use?
228 */
[3348]229 switch (aAudioDriver)
[1]230 {
[7207]231 case AudioDriverType_Null:
[3668]232#ifdef RT_OS_WINDOWS
[6056]233# ifdef VBOX_WITH_WINMM
[7466]234 case AudioDriverType_WinMM:
[6056]235# endif
[7466]236 case AudioDriverType_DirectSound:
[3668]237#endif /* RT_OS_WINDOWS */
[7525]238#ifdef RT_OS_SOLARIS
239 case AudioDriverType_SolAudio:
240#endif
[3668]241#ifdef RT_OS_LINUX
[7207]242 case AudioDriverType_OSS:
[6056]243# ifdef VBOX_WITH_ALSA
[7207]244 case AudioDriverType_ALSA:
[6056]245# endif
246# ifdef VBOX_WITH_PULSE
[7207]247 case AudioDriverType_Pulse:
[6056]248# endif
[3668]249#endif /* RT_OS_LINUX */
250#ifdef RT_OS_DARWIN
[7466]251 case AudioDriverType_CoreAudio:
[7207]252#endif
[3668]253#ifdef RT_OS_OS2
[7207]254 case AudioDriverType_MMPM:
255#endif
[1]256 {
257 mData.backup();
[3348]258 mData->mAudioDriver = aAudioDriver;
[1]259 break;
260 }
[1551]261
[1]262 default:
263 {
[3348]264 AssertMsgFailed (("Wrong audio driver type %d\n",
265 aAudioDriver));
[1]266 rc = E_FAIL;
267 }
268 }
269 }
270
271 return rc;
272}
273
[6597]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
[8083]282 AutoReadLock alock (this);
[6597]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
[8083]298 AutoWriteLock alock (this);
[6597]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
[1]327// IAudioAdapter methods
328/////////////////////////////////////////////////////////////////////////////
329
330// public methods only for internal purposes
331/////////////////////////////////////////////////////////////////////////////
332
[7207]333/**
[6076]334 * Loads settings from the given machine node.
335 * May be called once right after this object creation.
[7207]336 *
[6076]337 * @param aMachineNode <Machine> node.
[7207]338 *
339 * @note Locks this object for writing.
[6076]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
[8083]350 AutoWriteLock alock (this);
[6076]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
[7207]361 * default to B. */
[6076]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
[6597]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
[6076]376 /* now check the audio driver (required) */
377 const char *driver = audioAdapterNode.stringValue ("driver");
[7207]378 mData->mAudioDriver = AudioDriverType_Null;
[7466]379 if (strcmp (driver, "Null") == 0)
[6076]380 ; /* Null has been set above */
381#ifdef RT_OS_WINDOWS
[7466]382 else if (strcmp (driver, "WinMM") == 0)
[6076]383#ifdef VBOX_WITH_WINMM
[7466]384 mData->mAudioDriver = AudioDriverType_WinMM;
[6076]385#else
386 /* fall back to dsound */
[7466]387 mData->mAudioDriver = AudioDriverType_DirectSound;
[6076]388#endif
[7466]389 else if (strcmp (driver, "DirectSound") == 0)
390 mData->mAudioDriver = AudioDriverType_DirectSound;
[6076]391#endif // RT_OS_WINDOWS
[7525]392#ifdef RT_OS_SOLARIS
393 else if (strcmp (driver, "SolAudio") == 0)
394 mData->mAudioDriver = AudioDriverType_SolAudio;
395#endif // RT_OS_SOLARIS
[6076]396#ifdef RT_OS_LINUX
[7466]397 else if (strcmp (driver, "OSS") == 0)
[7207]398 mData->mAudioDriver = AudioDriverType_OSS;
[7466]399 else if (strcmp (driver, "ALSA") == 0)
[6076]400# ifdef VBOX_WITH_ALSA
[7207]401 mData->mAudioDriver = AudioDriverType_ALSA;
[6076]402# else
403 /* fall back to OSS */
[7207]404 mData->mAudioDriver = AudioDriverType_OSS;
[6076]405# endif
[7466]406 else if (strcmp (driver, "Pulse") == 0)
[6076]407# ifdef VBOX_WITH_PULSE
[7207]408 mData->mAudioDriver = AudioDriverType_Pulse;
[6076]409# else
410 /* fall back to OSS */
[7207]411 mData->mAudioDriver = AudioDriverType_OSS;
[6076]412# endif
413#endif // RT_OS_LINUX
414#ifdef RT_OS_DARWIN
[7466]415 else if (strcmp (driver, "CoreAudio") == 0)
416 mData->mAudioDriver = AudioDriverType_CoreAudio;
[6076]417#endif
418#ifdef RT_OS_OS2
[7466]419 else if (strcmp (driver, "MMPM") == 0)
[7207]420 mData->mAudioDriver = AudioDriverType_MMPM;
[6076]421#endif
422 else
423 AssertMsgFailed (("Invalid driver '%s'\n", driver));
424
425 return S_OK;
426}
427
[7207]428/**
[6076]429 * Saves settings to the given machine node.
[7207]430 *
[6076]431 * @param aMachineNode <Machine> node.
[7207]432 *
433 * @note Locks this object for reading.
[6076]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
[8083]444 AutoReadLock alock (this);
[6076]445
446 Key node = aMachineNode.createKey ("AudioAdapter");
447
[6597]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
[6076]464 const char *driverStr = NULL;
465 switch (mData->mAudioDriver)
466 {
[7207]467 case AudioDriverType_Null:
[6076]468 {
[7466]469 driverStr = "Null";
[6076]470 break;
471 }
472#ifdef RT_OS_WINDOWS
[7466]473 case AudioDriverType_WinMM:
[6076]474# ifdef VBOX_WITH_WINMM
475 {
[7466]476 driverStr = "WinMM";
[6076]477 break;
478 }
479# endif
[7466]480 case AudioDriverType_DirectSound:
[6076]481 {
[7466]482 driverStr = "DirectSound";
[6076]483 break;
484 }
485#endif /* RT_OS_WINDOWS */
[7525]486#ifdef RT_OS_SOLARIS
487 case AudioDriverType_SolAudio:
488 {
489 driverStr = "SolAudio";
490 break;
491 }
492#endif
[6076]493#ifdef RT_OS_LINUX
[7207]494 case AudioDriverType_ALSA:
[6076]495# ifdef VBOX_WITH_ALSA
496 {
[7466]497 driverStr = "ALSA";
[6076]498 break;
499 }
500# endif
[7207]501 case AudioDriverType_Pulse:
[6076]502# ifdef VBOX_WITH_PULSE
503 {
[7466]504 driverStr = "Pulse";
[6076]505 break;
506 }
507# endif
[7207]508 case AudioDriverType_OSS:
[6076]509 {
[7466]510 driverStr = "OSS";
[6076]511 break;
512 }
513#endif /* RT_OS_LINUX */
514#ifdef RT_OS_DARWIN
[7466]515 case AudioDriverType_CoreAudio:
[6076]516 {
[7466]517 driverStr = "CoreAudio";
[6076]518 break;
519 }
520#endif
521#ifdef RT_OS_OS2
[7207]522 case AudioDriverType_MMPM:
[6076]523 {
[7466]524 driverStr = "MMPM";
[6076]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
[7207]540/**
[3348]541 * @note Locks this object for writing.
542 */
543bool AudioAdapter::rollback()
[1]544{
[3348]545 /* sanity */
546 AutoCaller autoCaller (this);
547 AssertComRCReturn (autoCaller.rc(), false);
548
[8083]549 AutoWriteLock alock (this);
[3348]550
551 bool changed = false;
552
[1]553 if (mData.isBackedUp())
554 {
[3348]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
[7207]564/**
[3348]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 */
[7992]575 AutoCaller peerCaller (mPeer);
576 AssertComRCReturnVoid (peerCaller.rc());
[3348]577
[7992]578 /* lock both for writing since we modify both (mPeer is "master" so locked
579 * first) */
580 AutoMultiWriteLock2 alock (mPeer, this);
[3348]581
582 if (mData.isBackedUp())
583 {
[1]584 mData.commit();
585 if (mPeer)
586 {
[3348]587 /* attach new data to the peer and reshare it */
[1]588 mPeer->mData.attach (mData);
589 }
590 }
591}
592
[7207]593/**
[3348]594 * @note Locks this object for writing, together with the peer object
595 * represented by @a aThat (locked for reading).
596 */
[1]597void AudioAdapter::copyFrom (AudioAdapter *aThat)
598{
[3348]599 AssertReturnVoid (aThat != NULL);
[1]600
[3348]601 /* sanity */
602 AutoCaller autoCaller (this);
603 AssertComRCReturnVoid (autoCaller.rc());
604
605 /* sanity too */
[7992]606 AutoCaller thatCaller (aThat);
[3348]607 AssertComRCReturnVoid (thatCaller.rc());
608
[7992]609 /* peer is not modified, lock it for reading (aThat is "master" so locked
610 * first) */
611 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
[3348]612
613 /* this will back up current data */
[1]614 mData.assignCopy (aThat->mData);
615}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use