VirtualBox

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

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

Main: try to set a default audio driver

  • 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#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 AudioAdapter 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 */
369 const char *controller = audioAdapterNode.stringValue ("controller");
370 if (strcmp (controller, "SB16") == 0)
371 mData->mAudioController = AudioControllerType_SB16;
372 else if (strcmp (controller, "AC97") == 0)
373 mData->mAudioController = AudioControllerType_AC97;
374
375 /* now check the audio driver (required) */
376 const char *driver = audioAdapterNode.stringValue ("driver");
377 if (strcmp (driver, "Null") == 0)
378 mData->mAudioDriver = AudioDriverType_Null;
379#ifdef RT_OS_WINDOWS
380 else if (strcmp (driver, "WinMM") == 0)
381#ifdef VBOX_WITH_WINMM
382 mData->mAudioDriver = AudioDriverType_WinMM;
383#else
384 /* fall back to dsound */
385 mData->mAudioDriver = AudioDriverType_DirectSound;
386#endif
387 else if (strcmp (driver, "DirectSound") == 0)
388 mData->mAudioDriver = AudioDriverType_DirectSound;
389#endif // RT_OS_WINDOWS
390#ifdef RT_OS_SOLARIS
391 else if (strcmp (driver, "SolAudio") == 0)
392 mData->mAudioDriver = AudioDriverType_SolAudio;
393#endif // RT_OS_SOLARIS
394#ifdef RT_OS_LINUX
395 else if (strcmp (driver, "OSS") == 0)
396 mData->mAudioDriver = AudioDriverType_OSS;
397 else if (strcmp (driver, "ALSA") == 0)
398# ifdef VBOX_WITH_ALSA
399 mData->mAudioDriver = AudioDriverType_ALSA;
400# else
401 /* fall back to OSS */
402 mData->mAudioDriver = AudioDriverType_OSS;
403# endif
404 else if (strcmp (driver, "Pulse") == 0)
405# ifdef VBOX_WITH_PULSE
406 mData->mAudioDriver = AudioDriverType_Pulse;
407# else
408 /* fall back to OSS */
409 mData->mAudioDriver = AudioDriverType_OSS;
410# endif
411#endif // RT_OS_LINUX
412#ifdef RT_OS_DARWIN
413 else if (strcmp (driver, "CoreAudio") == 0)
414 mData->mAudioDriver = AudioDriverType_CoreAudio;
415#endif
416#ifdef RT_OS_OS2
417 else if (strcmp (driver, "MMPM") == 0)
418 mData->mAudioDriver = AudioDriverType_MMPM;
419#endif
420 else
421 AssertMsgFailed (("Invalid driver '%s'\n", driver));
422
423 return S_OK;
424}
425
426/**
427 * Saves settings to the given machine node.
428 *
429 * @param aMachineNode <Machine> node.
430 *
431 * @note Locks this object for reading.
432 */
433HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode)
434{
435 using namespace settings;
436
437 AssertReturn (!aMachineNode.isNull(), E_FAIL);
438
439 AutoCaller autoCaller (this);
440 AssertComRCReturnRC (autoCaller.rc());
441
442 AutoReadLock alock (this);
443
444 Key node = aMachineNode.createKey ("AudioAdapter");
445
446 const char *controllerStr = NULL;
447 switch (mData->mAudioController)
448 {
449 case AudioControllerType_SB16:
450 {
451 controllerStr = "SB16";
452 break;
453 }
454 default:
455 {
456 controllerStr = "AC97";
457 break;
458 }
459 }
460 node.setStringValue ("controller", controllerStr);
461
462 const char *driverStr = NULL;
463 switch (mData->mAudioDriver)
464 {
465 case AudioDriverType_Null:
466 {
467 driverStr = "Null";
468 break;
469 }
470#ifdef RT_OS_WINDOWS
471 case AudioDriverType_WinMM:
472# ifdef VBOX_WITH_WINMM
473 {
474 driverStr = "WinMM";
475 break;
476 }
477# endif
478 case AudioDriverType_DirectSound:
479 {
480 driverStr = "DirectSound";
481 break;
482 }
483#endif /* RT_OS_WINDOWS */
484#ifdef RT_OS_SOLARIS
485 case AudioDriverType_SolAudio:
486 {
487 driverStr = "SolAudio";
488 break;
489 }
490#endif
491#ifdef RT_OS_LINUX
492 case AudioDriverType_ALSA:
493# ifdef VBOX_WITH_ALSA
494 {
495 driverStr = "ALSA";
496 break;
497 }
498# endif
499 case AudioDriverType_Pulse:
500# ifdef VBOX_WITH_PULSE
501 {
502 driverStr = "Pulse";
503 break;
504 }
505# endif
506 case AudioDriverType_OSS:
507 {
508 driverStr = "OSS";
509 break;
510 }
511#endif /* RT_OS_LINUX */
512#ifdef RT_OS_DARWIN
513 case AudioDriverType_CoreAudio:
514 {
515 driverStr = "CoreAudio";
516 break;
517 }
518#endif
519#ifdef RT_OS_OS2
520 case AudioDriverType_MMPM:
521 {
522 driverStr = "MMPM";
523 break;
524 }
525#endif
526 default:
527 ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d",
528 mData->mAudioDriver),
529 E_FAIL);
530 }
531 node.setStringValue ("driver", driverStr);
532
533 node.setValue <bool> ("enabled", !!mData->mEnabled);
534
535 return S_OK;
536}
537
538/**
539 * @note Locks this object for writing.
540 */
541bool AudioAdapter::rollback()
542{
543 /* sanity */
544 AutoCaller autoCaller (this);
545 AssertComRCReturn (autoCaller.rc(), false);
546
547 AutoWriteLock alock (this);
548
549 bool changed = false;
550
551 if (mData.isBackedUp())
552 {
553 /* we need to check all data to see whether anything will be changed
554 * after rollback */
555 changed = mData.hasActualChanges();
556 mData.rollback();
557 }
558
559 return changed;
560}
561
562/**
563 * @note Locks this object for writing, together with the peer object (also
564 * for writing) if there is one.
565 */
566void AudioAdapter::commit()
567{
568 /* sanity */
569 AutoCaller autoCaller (this);
570 AssertComRCReturnVoid (autoCaller.rc());
571
572 /* sanity too */
573 AutoCaller peerCaller (mPeer);
574 AssertComRCReturnVoid (peerCaller.rc());
575
576 /* lock both for writing since we modify both (mPeer is "master" so locked
577 * first) */
578 AutoMultiWriteLock2 alock (mPeer, this);
579
580 if (mData.isBackedUp())
581 {
582 mData.commit();
583 if (mPeer)
584 {
585 /* attach new data to the peer and reshare it */
586 mPeer->mData.attach (mData);
587 }
588 }
589}
590
591/**
592 * @note Locks this object for writing, together with the peer object
593 * represented by @a aThat (locked for reading).
594 */
595void AudioAdapter::copyFrom (AudioAdapter *aThat)
596{
597 AssertReturnVoid (aThat != NULL);
598
599 /* sanity */
600 AutoCaller autoCaller (this);
601 AssertComRCReturnVoid (autoCaller.rc());
602
603 /* sanity too */
604 AutoCaller thatCaller (aThat);
605 AssertComRCReturnVoid (thatCaller.rc());
606
607 /* peer is not modified, lock it for reading (aThat is "master" so locked
608 * first) */
609 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
610
611 /* this will back up current data */
612 mData.assignCopy (aThat->mData);
613}
614/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use