VirtualBox

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

Last change on this file since 6381 was 6076, checked in by vboxsync, 17 years ago

Merged dmik/s2 branch (r25959:26751) to the trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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
18#include "AudioAdapterImpl.h"
19#include "MachineImpl.h"
20#include "Logging.h"
21
22#include <iprt/cpputils.h>
23
24// constructor / destructor
25/////////////////////////////////////////////////////////////////////////////
26
27DEFINE_EMPTY_CTOR_DTOR (AudioAdapter)
28
29HRESULT AudioAdapter::FinalConstruct()
30{
31 return S_OK;
32}
33
34void AudioAdapter::FinalRelease()
35{
36 uninit ();
37}
38
39// public initializer/uninitializer for internal purposes only
40/////////////////////////////////////////////////////////////////////////////
41
42/**
43 * Initializes the audio adapter object.
44 *
45 * @param aParent Handle of the parent object.
46 */
47HRESULT AudioAdapter::init (Machine *aParent)
48{
49 LogFlowThisFunc (("aParent=%p\n", aParent));
50
51 ComAssertRet (aParent, E_INVALIDARG);
52
53 /* Enclose the state transition NotReady->InInit->Ready */
54 AutoInitSpan autoInitSpan (this);
55 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
56
57 unconst (mParent) = aParent;
58 /* mPeer is left null */
59
60 mData.allocate();
61
62 /* Confirm a successful initialization */
63 autoInitSpan.setSucceeded();
64
65 return S_OK;
66}
67
68/**
69 * Initializes the audio adapter object given another audio adapter object
70 * (a kind of copy constructor). This object shares data with
71 * the object passed as an argument.
72 *
73 * @note This object must be destroyed before the original object
74 * it shares data with is destroyed.
75 *
76 * @note Locks @a aThat object for reading.
77 */
78HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
79{
80 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
81
82 ComAssertRet (aParent && aThat, E_INVALIDARG);
83
84 /* Enclose the state transition NotReady->InInit->Ready */
85 AutoInitSpan autoInitSpan (this);
86 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
87
88 unconst (mParent) = aParent;
89 unconst (mPeer) = aThat;
90
91 AutoCaller thatCaller (aThat);
92 AssertComRCReturnRC (thatCaller.rc());
93
94 AutoReaderLock thatLock (aThat);
95 mData.share (aThat->mData);
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Initializes the guest object given another guest object
105 * (a kind of copy constructor). This object makes a private copy of data
106 * of the original object passed as an argument.
107 *
108 * @note Locks @a aThat object for reading.
109 */
110HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
111{
112 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
113
114 ComAssertRet (aParent && aThat, E_INVALIDARG);
115
116 /* Enclose the state transition NotReady->InInit->Ready */
117 AutoInitSpan autoInitSpan (this);
118 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
119
120 unconst (mParent) = aParent;
121 /* mPeer is left null */
122
123 AutoCaller thatCaller (aThat);
124 AssertComRCReturnRC (thatCaller.rc());
125
126 AutoReaderLock thatLock (aThat);
127 mData.attachCopy (aThat->mData);
128
129 /* Confirm a successful initialization */
130 autoInitSpan.setSucceeded();
131
132 return S_OK;
133}
134
135/**
136 * Uninitializes the instance and sets the ready flag to FALSE.
137 * Called either from FinalRelease() or by the parent when it gets destroyed.
138 */
139void AudioAdapter::uninit()
140{
141 LogFlowThisFunc (("\n"));
142
143 /* Enclose the state transition Ready->InUninit->NotReady */
144 AutoUninitSpan autoUninitSpan (this);
145 if (autoUninitSpan.uninitDone())
146 return;
147
148 mData.free();
149
150 unconst (mPeer).setNull();
151 unconst (mParent).setNull();
152}
153
154// IAudioAdapter properties
155/////////////////////////////////////////////////////////////////////////////
156
157STDMETHODIMP AudioAdapter::COMGETTER(Enabled)(BOOL *aEnabled)
158{
159 if (!aEnabled)
160 return E_POINTER;
161
162 AutoCaller autoCaller (this);
163 CheckComRCReturnRC (autoCaller.rc());
164
165 AutoReaderLock alock (this);
166
167 *aEnabled = mData->mEnabled;
168
169 return S_OK;
170}
171
172STDMETHODIMP AudioAdapter::COMSETTER(Enabled)(BOOL aEnabled)
173{
174 AutoCaller autoCaller (this);
175 CheckComRCReturnRC (autoCaller.rc());
176
177 /* the machine needs to be mutable */
178 Machine::AutoMutableStateDependency adep (mParent);
179 CheckComRCReturnRC (adep.rc());
180
181 AutoLock alock (this);
182
183 if (mData->mEnabled != aEnabled)
184 {
185 mData.backup();
186 mData->mEnabled = aEnabled;
187 }
188
189 return S_OK;
190}
191
192STDMETHODIMP AudioAdapter::COMGETTER(AudioDriver)(AudioDriverType_T *aAudioDriver)
193{
194 if (!aAudioDriver)
195 return E_POINTER;
196
197 AutoCaller autoCaller (this);
198 CheckComRCReturnRC (autoCaller.rc());
199
200 AutoReaderLock alock (this);
201
202 *aAudioDriver = mData->mAudioDriver;
203
204 return S_OK;
205}
206
207STDMETHODIMP AudioAdapter::COMSETTER(AudioDriver)(AudioDriverType_T aAudioDriver)
208{
209 AutoCaller autoCaller (this);
210 CheckComRCReturnRC (autoCaller.rc());
211
212 /* the machine needs to be mutable */
213 Machine::AutoMutableStateDependency adep (mParent);
214 CheckComRCReturnRC (adep.rc());
215
216 AutoLock alock (this);
217
218 HRESULT rc = S_OK;
219
220 if (mData->mAudioDriver != aAudioDriver)
221 {
222 /*
223 * which audio driver type are we supposed to use?
224 */
225 switch (aAudioDriver)
226 {
227 case AudioDriverType_NullAudioDriver:
228#ifdef RT_OS_WINDOWS
229# ifdef VBOX_WITH_WINMM
230 case AudioDriverType_WINMMAudioDriver:
231# endif
232 case AudioDriverType_DSOUNDAudioDriver:
233#endif /* RT_OS_WINDOWS */
234#ifdef RT_OS_LINUX
235 case AudioDriverType_OSSAudioDriver:
236# ifdef VBOX_WITH_ALSA
237 case AudioDriverType_ALSAAudioDriver:
238# endif
239# ifdef VBOX_WITH_PULSE
240 case AudioDriverType_PulseAudioDriver:
241# endif
242#endif /* RT_OS_LINUX */
243#ifdef RT_OS_DARWIN
244 case AudioDriverType_CoreAudioDriver:
245#endif
246#ifdef RT_OS_OS2
247 case AudioDriverType_MMPMAudioDriver:
248#endif
249 {
250 mData.backup();
251 mData->mAudioDriver = aAudioDriver;
252 break;
253 }
254
255 default:
256 {
257 AssertMsgFailed (("Wrong audio driver type %d\n",
258 aAudioDriver));
259 rc = E_FAIL;
260 }
261 }
262 }
263
264 return rc;
265}
266
267// IAudioAdapter methods
268/////////////////////////////////////////////////////////////////////////////
269
270// public methods only for internal purposes
271/////////////////////////////////////////////////////////////////////////////
272
273/**
274 * Loads settings from the given machine node.
275 * May be called once right after this object creation.
276 *
277 * @param aMachineNode <Machine> node.
278 *
279 * @note Locks this object for writing.
280 */
281HRESULT AudioAdapter::loadSettings (const settings::Key &aMachineNode)
282{
283 using namespace settings;
284
285 AssertReturn (!aMachineNode.isNull(), E_FAIL);
286
287 AutoCaller autoCaller (this);
288 AssertComRCReturnRC (autoCaller.rc());
289
290 AutoLock alock (this);
291
292 /* Note: we assume that the default values for attributes of optional
293 * nodes are assigned in the Data::Data() constructor and don't do it
294 * here. It implies that this method may only be called after constructing
295 * a new BIOSSettings object while all its data fields are in the default
296 * values. Exceptions are fields whose creation time defaults don't match
297 * values that should be applied when these fields are not explicitly set
298 * in the settings file (for backwards compatibility reasons). This takes
299 * place when a setting of a newly created object must default to A while
300 * the same setting of an object loaded from the old settings file must
301 * default to B. */
302
303 /* AudioAdapter node (required) */
304 Key audioAdapterNode = aMachineNode.key ("AudioAdapter");
305
306 /* is the adapter enabled? (required) */
307 mData->mEnabled = audioAdapterNode.value <bool> ("enabled");
308
309 /* now check the audio driver (required) */
310 const char *driver = audioAdapterNode.stringValue ("driver");
311 mData->mAudioDriver = AudioDriverType_NullAudioDriver;
312 if (strcmp (driver, "null") == 0)
313 ; /* Null has been set above */
314#ifdef RT_OS_WINDOWS
315 else if (strcmp (driver, "winmm") == 0)
316#ifdef VBOX_WITH_WINMM
317 mData->mAudioDriver = AudioDriverType_WINMMAudioDriver;
318#else
319 /* fall back to dsound */
320 mData->mAudioDriver = AudioDriverType_DSOUNDAudioDriver;
321#endif
322 else if (strcmp (driver, "dsound") == 0)
323 mData->mAudioDriver = AudioDriverType_DSOUNDAudioDriver;
324#endif // RT_OS_WINDOWS
325#ifdef RT_OS_LINUX
326 else if (strcmp (driver, "oss") == 0)
327 mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
328 else if (strcmp (driver, "alsa") == 0)
329# ifdef VBOX_WITH_ALSA
330 mData->mAudioDriver = AudioDriverType_ALSAAudioDriver;
331# else
332 /* fall back to OSS */
333 mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
334# endif
335 else if (strcmp (driver, "pulse") == 0)
336# ifdef VBOX_WITH_PULSE
337 mData->mAudioDriver = AudioDriverType_PulseAudioDriver;
338# else
339 /* fall back to OSS */
340 mData->mAudioDriver = AudioDriverType_OSSAudioDriver;
341# endif
342#endif // RT_OS_LINUX
343#ifdef RT_OS_DARWIN
344 else if (strcmp (driver, "coreaudio") == 0)
345 mData->mAudioDriver = AudioDriverType_CoreAudioDriver;
346#endif
347#ifdef RT_OS_OS2
348 else if (strcmp (driver, "mmpm") == 0)
349 mData->mAudioDriver = AudioDriverType_MMPMAudioDriver;
350#endif
351 else
352 AssertMsgFailed (("Invalid driver '%s'\n", driver));
353
354 return S_OK;
355}
356
357/**
358 * Saves settings to the given machine node.
359 *
360 * @param aMachineNode <Machine> node.
361 *
362 * @note Locks this object for reading.
363 */
364HRESULT AudioAdapter::saveSettings (settings::Key &aMachineNode)
365{
366 using namespace settings;
367
368 AssertReturn (!aMachineNode.isNull(), E_FAIL);
369
370 AutoCaller autoCaller (this);
371 AssertComRCReturnRC (autoCaller.rc());
372
373 AutoReaderLock alock (this);
374
375 Key node = aMachineNode.createKey ("AudioAdapter");
376
377 const char *driverStr = NULL;
378 switch (mData->mAudioDriver)
379 {
380 case AudioDriverType_NullAudioDriver:
381 {
382 driverStr = "null";
383 break;
384 }
385#ifdef RT_OS_WINDOWS
386 case AudioDriverType_WINMMAudioDriver:
387# ifdef VBOX_WITH_WINMM
388 {
389 driverStr = "winmm";
390 break;
391 }
392# endif
393 case AudioDriverType_DSOUNDAudioDriver:
394 {
395 driverStr = "dsound";
396 break;
397 }
398#endif /* RT_OS_WINDOWS */
399#ifdef RT_OS_LINUX
400 case AudioDriverType_ALSAAudioDriver:
401# ifdef VBOX_WITH_ALSA
402 {
403 driverStr = "alsa";
404 break;
405 }
406# endif
407 case AudioDriverType_PulseAudioDriver:
408# ifdef VBOX_WITH_PULSE
409 {
410 driverStr = "pulse";
411 break;
412 }
413# endif
414 case AudioDriverType_OSSAudioDriver:
415 {
416 driverStr = "oss";
417 break;
418 }
419#endif /* RT_OS_LINUX */
420#ifdef RT_OS_DARWIN
421 case AudioDriverType_CoreAudioDriver:
422 {
423 driverStr = "coreaudio";
424 break;
425 }
426#endif
427#ifdef RT_OS_OS2
428 case AudioDriverType_MMPMAudioDriver:
429 {
430 driverStr = "mmpm";
431 break;
432 }
433#endif
434 default:
435 ComAssertMsgFailedRet (("Wrong audio driver type! driver = %d\n",
436 mData->mAudioDriver),
437 E_FAIL);
438 }
439 node.setStringValue ("driver", driverStr);
440
441 node.setValue <bool> ("enabled", !!mData->mEnabled);
442
443 return S_OK;
444}
445
446/**
447 * @note Locks this object for writing.
448 */
449bool AudioAdapter::rollback()
450{
451 /* sanity */
452 AutoCaller autoCaller (this);
453 AssertComRCReturn (autoCaller.rc(), false);
454
455 AutoLock alock (this);
456
457 bool changed = false;
458
459 if (mData.isBackedUp())
460 {
461 /* we need to check all data to see whether anything will be changed
462 * after rollback */
463 changed = mData.hasActualChanges();
464 mData.rollback();
465 }
466
467 return changed;
468}
469
470/**
471 * @note Locks this object for writing, together with the peer object (also
472 * for writing) if there is one.
473 */
474void AudioAdapter::commit()
475{
476 /* sanity */
477 AutoCaller autoCaller (this);
478 AssertComRCReturnVoid (autoCaller.rc());
479
480 /* sanity too */
481 AutoCaller thatCaller (mPeer);
482 AssertComRCReturnVoid (thatCaller.rc());
483
484 /* lock both for writing since we modify both */
485 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
486
487 if (mData.isBackedUp())
488 {
489 mData.commit();
490 if (mPeer)
491 {
492 /* attach new data to the peer and reshare it */
493 mPeer->mData.attach (mData);
494 }
495 }
496}
497
498/**
499 * @note Locks this object for writing, together with the peer object
500 * represented by @a aThat (locked for reading).
501 */
502void AudioAdapter::copyFrom (AudioAdapter *aThat)
503{
504 AssertReturnVoid (aThat != NULL);
505
506 /* sanity */
507 AutoCaller autoCaller (this);
508 AssertComRCReturnVoid (autoCaller.rc());
509
510 /* sanity too */
511 AutoCaller thatCaller (mPeer);
512 AssertComRCReturnVoid (thatCaller.rc());
513
514 /* peer is not modified, lock it for reading */
515 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
516
517 /* this will back up current data */
518 mData.assignCopy (aThat->mData);
519}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette