VirtualBox

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

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

Main: do not include include/VBox/settings.h from other header files but only from implementations that need it (save compile time)

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

© 2023 Oracle
ContactPrivacy policyTerms of Use