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
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#include <VBox/settings.h>
29
30// constructor / destructor
31/////////////////////////////////////////////////////////////////////////////
32
33DEFINE_EMPTY_CTOR_DTOR (AudioAdapter)
34
35HRESULT AudioAdapter::FinalConstruct()
36{
37 return S_OK;
38}
39
40void AudioAdapter::FinalRelease()
41{
42 uninit ();
43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the audio adapter object.
50 *
51 * @param aParent Handle of the parent object.
52 */
53HRESULT AudioAdapter::init (Machine *aParent)
54{
55 LogFlowThisFunc (("aParent=%p\n", aParent));
56
57 ComAssertRet (aParent, E_INVALIDARG);
58
59 /* Enclose the state transition NotReady->InInit->Ready */
60 AutoInitSpan autoInitSpan (this);
61 AssertReturn (autoInitSpan.isOk(), E_FAIL);
62
63 unconst (mParent) = aParent;
64 /* mPeer is left null */
65
66 mData.allocate();
67
68 /* Confirm a successful initialization */
69 autoInitSpan.setSucceeded();
70
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.
81 *
82 * @note Locks @a aThat object for reading.
83 */
84HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
85{
86 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
87
88 ComAssertRet (aParent && aThat, E_INVALIDARG);
89
90 /* Enclose the state transition NotReady->InInit->Ready */
91 AutoInitSpan autoInitSpan (this);
92 AssertReturn (autoInitSpan.isOk(), E_FAIL);
93
94 unconst (mParent) = aParent;
95 unconst (mPeer) = aThat;
96
97 AutoCaller thatCaller (aThat);
98 AssertComRCReturnRC (thatCaller.rc());
99
100 AutoReadLock thatLock (aThat);
101 mData.share (aThat->mData);
102
103 /* Confirm a successful initialization */
104 autoInitSpan.setSucceeded();
105
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.
113 *
114 * @note Locks @a aThat object for reading.
115 */
116HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
117{
118 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
119
120 ComAssertRet (aParent && aThat, E_INVALIDARG);
121
122 /* Enclose the state transition NotReady->InInit->Ready */
123 AutoInitSpan autoInitSpan (this);
124 AssertReturn (autoInitSpan.isOk(), E_FAIL);
125
126 unconst (mParent) = aParent;
127 /* mPeer is left null */
128
129 AutoCaller thatCaller (aThat);
130 AssertComRCReturnRC (thatCaller.rc());
131
132 AutoReadLock thatLock (aThat);
133 mData.attachCopy (aThat->mData);
134
135 /* Confirm a successful initialization */
136 autoInitSpan.setSucceeded();
137
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{
147 LogFlowThisFunc (("\n"));
148
149 /* Enclose the state transition Ready->InUninit->NotReady */
150 AutoUninitSpan autoUninitSpan (this);
151 if (autoUninitSpan.uninitDone())
152 return;
153
154 mData.free();
155
156 unconst (mPeer).setNull();
157 unconst (mParent).setNull();
158}
159
160// IAudioAdapter properties
161/////////////////////////////////////////////////////////////////////////////
162
163STDMETHODIMP AudioAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
164{
165 CheckComArgOutPointerValid(aEnabled);
166
167 AutoCaller autoCaller (this);
168 CheckComRCReturnRC (autoCaller.rc());
169
170 AutoReadLock alock (this);
171
172 *aEnabled = mData->mEnabled;
173
174 return S_OK;
175}
176
177STDMETHODIMP AudioAdapter::COMSETTER(Enabled)(BOOL aEnabled)
178{
179 AutoCaller autoCaller (this);
180 CheckComRCReturnRC (autoCaller.rc());
181
182 /* the machine needs to be mutable */
183 Machine::AutoMutableStateDependency adep (mParent);
184 CheckComRCReturnRC (adep.rc());
185
186 AutoWriteLock alock (this);
187
188 if (mData->mEnabled != aEnabled)
189 {
190 mData.backup();
191 mData->mEnabled = aEnabled;
192 }
193
194 return S_OK;
195}
196
197STDMETHODIMP AudioAdapter::COMGETTER(AudioDriver)(AudioDriverType_T *aAudioDriver)
198{
199 CheckComArgOutPointerValid(aAudioDriver);
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 CheckComArgOutPointerValid(aAudioController);
277
278 AutoCaller autoCaller (this);
279 CheckComRCReturnRC (autoCaller.rc());
280
281 AutoReadLock alock (this);
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
297 AutoWriteLock alock (this);
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
326// IAudioAdapter methods
327/////////////////////////////////////////////////////////////////////////////
328
329// public methods only for internal purposes
330/////////////////////////////////////////////////////////////////////////////
331
332/**
333 * Loads settings from the given machine node.
334 * May be called once right after this object creation.
335 *
336 * @param aMachineNode <Machine> node.
337 *
338 * @note Locks this object for writing.
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
349 AutoWriteLock alock (this);
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
360 * default to B. */
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
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
375 /* now check the audio driver (required) */
376 const char *driver = audioAdapterNode.stringValue ("driver");
377 mData->mAudioDriver = AudioDriverType_Null;
378 if (strcmp (driver, "Null") == 0)
379 ; /* Null has been set above */
380#ifdef RT_OS_WINDOWS
381 else if (strcmp (driver, "WinMM") == 0)
382#ifdef VBOX_WITH_WINMM
383 mData->mAudioDriver = AudioDriverType_WinMM;
384#else
385 /* fall back to dsound */
386 mData->mAudioDriver = AudioDriverType_DirectSound;
387#endif
388 else if (strcmp (driver, "DirectSound") == 0)
389 mData->mAudioDriver = AudioDriverType_DirectSound;
390#endif // RT_OS_WINDOWS
391#ifdef RT_OS_SOLARIS
392 else if (strcmp (driver, "SolAudio") == 0)
393 mData->mAudioDriver = AudioDriverType_SolAudio;
394#endif // RT_OS_SOLARIS
395#ifdef RT_OS_LINUX
396 else if (strcmp (driver, "OSS") == 0)
397 mData->mAudioDriver = AudioDriverType_OSS;
398 else if (strcmp (driver, "ALSA") == 0)
399# ifdef VBOX_WITH_ALSA
400 mData->mAudioDriver = AudioDriverType_ALSA;
401# else
402 /* fall back to OSS */
403 mData->mAudioDriver = AudioDriverType_OSS;
404# endif
405 else if (strcmp (driver, "Pulse") == 0)
406# ifdef VBOX_WITH_PULSE
407 mData->mAudioDriver = AudioDriverType_Pulse;
408# else
409 /* fall back to OSS */
410 mData->mAudioDriver = AudioDriverType_OSS;
411# endif
412#endif // RT_OS_LINUX
413#ifdef RT_OS_DARWIN
414 else if (strcmp (driver, "CoreAudio") == 0)
415 mData->mAudioDriver = AudioDriverType_CoreAudio;
416#endif
417#ifdef RT_OS_OS2
418 else if (strcmp (driver, "MMPM") == 0)
419 mData->mAudioDriver = AudioDriverType_MMPM;
420#endif
421 else
422 AssertMsgFailed (("Invalid driver '%s'\n", driver));
423
424 return S_OK;
425}
426
427/**
428 * Saves settings to the given machine node.
429 *
430 * @param aMachineNode <Machine> node.
431 *
432 * @note Locks this object for reading.
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
443 AutoReadLock alock (this);
444
445 Key node = aMachineNode.createKey ("AudioAdapter");
446
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
463 const char *driverStr = NULL;
464 switch (mData->mAudioDriver)
465 {
466 case AudioDriverType_Null:
467 {
468 driverStr = "Null";
469 break;
470 }
471#ifdef RT_OS_WINDOWS
472 case AudioDriverType_WinMM:
473# ifdef VBOX_WITH_WINMM
474 {
475 driverStr = "WinMM";
476 break;
477 }
478# endif
479 case AudioDriverType_DirectSound:
480 {
481 driverStr = "DirectSound";
482 break;
483 }
484#endif /* RT_OS_WINDOWS */
485#ifdef RT_OS_SOLARIS
486 case AudioDriverType_SolAudio:
487 {
488 driverStr = "SolAudio";
489 break;
490 }
491#endif
492#ifdef RT_OS_LINUX
493 case AudioDriverType_ALSA:
494# ifdef VBOX_WITH_ALSA
495 {
496 driverStr = "ALSA";
497 break;
498 }
499# endif
500 case AudioDriverType_Pulse:
501# ifdef VBOX_WITH_PULSE
502 {
503 driverStr = "Pulse";
504 break;
505 }
506# endif
507 case AudioDriverType_OSS:
508 {
509 driverStr = "OSS";
510 break;
511 }
512#endif /* RT_OS_LINUX */
513#ifdef RT_OS_DARWIN
514 case AudioDriverType_CoreAudio:
515 {
516 driverStr = "CoreAudio";
517 break;
518 }
519#endif
520#ifdef RT_OS_OS2
521 case AudioDriverType_MMPM:
522 {
523 driverStr = "MMPM";
524 break;
525 }
526#endif
527 default:
528 ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d",
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
539/**
540 * @note Locks this object for writing.
541 */
542bool AudioAdapter::rollback()
543{
544 /* sanity */
545 AutoCaller autoCaller (this);
546 AssertComRCReturn (autoCaller.rc(), false);
547
548 AutoWriteLock alock (this);
549
550 bool changed = false;
551
552 if (mData.isBackedUp())
553 {
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
563/**
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 */
574 AutoCaller peerCaller (mPeer);
575 AssertComRCReturnVoid (peerCaller.rc());
576
577 /* lock both for writing since we modify both (mPeer is "master" so locked
578 * first) */
579 AutoMultiWriteLock2 alock (mPeer, this);
580
581 if (mData.isBackedUp())
582 {
583 mData.commit();
584 if (mPeer)
585 {
586 /* attach new data to the peer and reshare it */
587 mPeer->mData.attach (mData);
588 }
589 }
590}
591
592/**
593 * @note Locks this object for writing, together with the peer object
594 * represented by @a aThat (locked for reading).
595 */
596void AudioAdapter::copyFrom (AudioAdapter *aThat)
597{
598 AssertReturnVoid (aThat != NULL);
599
600 /* sanity */
601 AutoCaller autoCaller (this);
602 AssertComRCReturnVoid (autoCaller.rc());
603
604 /* sanity too */
605 AutoCaller thatCaller (aThat);
606 AssertComRCReturnVoid (thatCaller.rc());
607
608 /* peer is not modified, lock it for reading (aThat is "master" so locked
609 * first) */
610 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
611
612 /* this will back up current data */
613 mData.assignCopy (aThat->mData);
614}
615/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use