VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/AudioAdapterImpl.cpp@ 67954

Last change on this file since 67954 was 65063, checked in by vboxsync, 8 years ago

Main: doxygen fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/* $Id: AudioAdapterImpl.cpp 65063 2017-01-03 11:15:49Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2016 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "AudioAdapterImpl.h"
20#include "MachineImpl.h"
21
22#include <iprt/cpp/utils.h>
23
24#include <VBox/settings.h>
25
26#include "AutoStateDep.h"
27#include "AutoCaller.h"
28#include "Logging.h"
29
30
31// constructor / destructor
32/////////////////////////////////////////////////////////////////////////////
33
34AudioAdapter::AudioAdapter()
35 : mParent(NULL)
36{
37}
38
39AudioAdapter::~AudioAdapter()
40{
41}
42
43HRESULT AudioAdapter::FinalConstruct()
44{
45 return BaseFinalConstruct();
46}
47
48void AudioAdapter::FinalRelease()
49{
50 uninit();
51 BaseFinalRelease();
52}
53
54// public initializer/uninitializer for internal purposes only
55/////////////////////////////////////////////////////////////////////////////
56
57/**
58 * Initializes the audio adapter object.
59 *
60 * @param aParent Handle of the parent object.
61 */
62HRESULT AudioAdapter::init(Machine *aParent)
63{
64 LogFlowThisFunc(("aParent=%p\n", aParent));
65
66 ComAssertRet(aParent, E_INVALIDARG);
67
68 /* Enclose the state transition NotReady->InInit->Ready */
69 AutoInitSpan autoInitSpan(this);
70 AssertReturn(autoInitSpan.isOk(), E_FAIL);
71
72 /* Get the default audio driver out of the system properties */
73 ComPtr<IVirtualBox> VBox;
74 HRESULT rc = aParent->COMGETTER(Parent)(VBox.asOutParam());
75 if (FAILED(rc)) return rc;
76 ComPtr<ISystemProperties> sysProps;
77 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
78 if (FAILED(rc)) return rc;
79 AudioDriverType_T defaultAudioDriver;
80 rc = sysProps->COMGETTER(DefaultAudioDriver)(&defaultAudioDriver);
81 if (FAILED(rc)) return rc;
82
83 unconst(mParent) = aParent;
84 /* mPeer is left null */
85
86 mData.allocate();
87 mData->driverType = defaultAudioDriver;
88
89 /* Confirm a successful initialization */
90 autoInitSpan.setSucceeded();
91
92 return S_OK;
93}
94
95/**
96 * Initializes the audio adapter object given another audio adapter object
97 * (a kind of copy constructor). This object shares data with
98 * the object passed as an argument.
99 *
100 * @note This object must be destroyed before the original object
101 * it shares data with is destroyed.
102 *
103 * @note Locks @a aThat object for reading.
104 */
105HRESULT AudioAdapter::init(Machine *aParent, AudioAdapter *aThat)
106{
107 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
108
109 ComAssertRet(aParent && aThat, E_INVALIDARG);
110
111 /* Enclose the state transition NotReady->InInit->Ready */
112 AutoInitSpan autoInitSpan(this);
113 AssertReturn(autoInitSpan.isOk(), E_FAIL);
114
115 unconst(mParent) = aParent;
116 unconst(mPeer) = aThat;
117
118 AutoCaller thatCaller(aThat);
119 AssertComRCReturnRC(thatCaller.rc());
120
121 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
122 mData.share(aThat->mData);
123
124 /* Confirm a successful initialization */
125 autoInitSpan.setSucceeded();
126
127 return S_OK;
128}
129
130/**
131 * Initializes the guest object given another guest object
132 * (a kind of copy constructor). This object makes a private copy of data
133 * of the original object passed as an argument.
134 *
135 * @note Locks @a aThat object for reading.
136 */
137HRESULT AudioAdapter::initCopy(Machine *aParent, AudioAdapter *aThat)
138{
139 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
140
141 ComAssertRet(aParent && aThat, E_INVALIDARG);
142
143 /* Enclose the state transition NotReady->InInit->Ready */
144 AutoInitSpan autoInitSpan(this);
145 AssertReturn(autoInitSpan.isOk(), E_FAIL);
146
147 unconst(mParent) = aParent;
148 /* mPeer is left null */
149
150 AutoCaller thatCaller(aThat);
151 AssertComRCReturnRC(thatCaller.rc());
152
153 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
154 mData.attachCopy(aThat->mData);
155
156 /* Confirm a successful initialization */
157 autoInitSpan.setSucceeded();
158
159 return S_OK;
160}
161
162/**
163 * Uninitializes the instance and sets the ready flag to FALSE.
164 * Called either from FinalRelease() or by the parent when it gets destroyed.
165 */
166void AudioAdapter::uninit()
167{
168 LogFlowThisFunc(("\n"));
169
170 /* Enclose the state transition Ready->InUninit->NotReady */
171 AutoUninitSpan autoUninitSpan(this);
172 if (autoUninitSpan.uninitDone())
173 return;
174
175 mData.free();
176
177 unconst(mPeer) = NULL;
178 unconst(mParent) = NULL;
179}
180
181// IAudioAdapter properties
182/////////////////////////////////////////////////////////////////////////////
183
184HRESULT AudioAdapter::getEnabled(BOOL *aEnabled)
185{
186 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
187
188 *aEnabled = mData->fEnabled;
189
190 return S_OK;
191}
192
193HRESULT AudioAdapter::setEnabled(BOOL aEnabled)
194{
195 /* the machine needs to be mutable */
196 AutoMutableStateDependency adep(mParent);
197 if (FAILED(adep.rc())) return adep.rc();
198
199 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
200
201 if (mData->fEnabled != RT_BOOL(aEnabled))
202 {
203 mData.backup();
204 mData->fEnabled = RT_BOOL(aEnabled);
205
206 alock.release();
207 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
208 mParent->i_setModified(Machine::IsModified_AudioAdapter);
209 }
210
211 return S_OK;
212}
213
214HRESULT AudioAdapter::getEnabledIn(BOOL *aEnabled)
215{
216 NOREF(aEnabled);
217 return E_NOTIMPL;
218}
219
220HRESULT AudioAdapter::setEnabledIn(BOOL aEnabled)
221{
222 NOREF(aEnabled);
223 return E_NOTIMPL;
224}
225
226HRESULT AudioAdapter::getEnabledOut(BOOL *aEnabled)
227{
228 NOREF(aEnabled);
229 return E_NOTIMPL;
230}
231
232HRESULT AudioAdapter::setEnabledOut(BOOL aEnabled)
233{
234 NOREF(aEnabled);
235 return E_NOTIMPL;
236}
237
238HRESULT AudioAdapter::getAudioDriver(AudioDriverType_T *aAudioDriver)
239{
240 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
241
242 *aAudioDriver = mData->driverType;
243
244 return S_OK;
245}
246
247HRESULT AudioAdapter::setAudioDriver(AudioDriverType_T aAudioDriver)
248{
249
250 /* the machine needs to be mutable */
251 AutoMutableOrSavedStateDependency adep(mParent);
252 if (FAILED(adep.rc())) return adep.rc();
253
254 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
255
256 HRESULT rc = S_OK;
257
258 if (mData->driverType != aAudioDriver)
259 {
260 if (settings::MachineConfigFile::isAudioDriverAllowedOnThisHost(aAudioDriver))
261 {
262 mData.backup();
263 mData->driverType = aAudioDriver;
264 alock.release();
265 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
266 mParent->i_setModified(Machine::IsModified_AudioAdapter);
267 }
268 else
269 {
270 AssertMsgFailed(("Wrong audio driver type %d\n", aAudioDriver));
271 rc = E_FAIL;
272 }
273 }
274
275 return rc;
276}
277
278HRESULT AudioAdapter::getAudioController(AudioControllerType_T *aAudioController)
279{
280 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
281
282 *aAudioController = mData->controllerType;
283
284 return S_OK;
285}
286
287HRESULT AudioAdapter::setAudioController(AudioControllerType_T aAudioController)
288{
289 /* the machine needs to be mutable */
290 AutoMutableStateDependency adep(mParent);
291 if (FAILED(adep.rc())) return adep.rc();
292
293 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
294
295 HRESULT rc = S_OK;
296
297 if (mData->controllerType != aAudioController)
298 {
299 AudioCodecType_T defaultCodec;
300
301 /*
302 * which audio hardware type are we supposed to use?
303 */
304 switch (aAudioController)
305 {
306 /* codec type needs to match the controller. */
307 case AudioControllerType_AC97:
308 defaultCodec = AudioCodecType_STAC9700;
309 break;
310 case AudioControllerType_SB16:
311 defaultCodec = AudioCodecType_SB16;
312 break;
313 case AudioControllerType_HDA:
314 defaultCodec = AudioCodecType_STAC9221;
315 break;
316
317 default:
318 AssertMsgFailed(("Wrong audio controller type %d\n", aAudioController));
319 defaultCodec = AudioCodecType_Null; /* Shut up MSC */
320 rc = E_FAIL;
321 }
322 if (rc == S_OK)
323 {
324 mData.backup();
325 mData->controllerType = aAudioController;
326 mData->codecType = defaultCodec;
327 alock.release();
328 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
329 mParent->i_setModified(Machine::IsModified_AudioAdapter);
330 }
331 }
332
333 return rc;
334}
335
336HRESULT AudioAdapter::getAudioCodec(AudioCodecType_T *aAudioCodec)
337{
338 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
339
340 *aAudioCodec = mData->codecType;
341
342 return S_OK;
343}
344
345HRESULT AudioAdapter::setAudioCodec(AudioCodecType_T aAudioCodec)
346{
347 /* the machine needs to be mutable */
348 AutoMutableStateDependency adep(mParent);
349 if (FAILED(adep.rc())) return adep.rc();
350
351 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
352
353 HRESULT rc = S_OK;
354
355 /*
356 * ensure that the codec type matches the audio controller
357 */
358 switch (mData->controllerType)
359 {
360 case AudioControllerType_AC97:
361 {
362 if ( (aAudioCodec != AudioCodecType_STAC9700)
363 && (aAudioCodec != AudioCodecType_AD1980))
364 rc = E_INVALIDARG;
365 break;
366 }
367
368 case AudioControllerType_SB16:
369 {
370 if (aAudioCodec != AudioCodecType_SB16)
371 rc = E_INVALIDARG;
372 break;
373 }
374
375 case AudioControllerType_HDA:
376 {
377 if (aAudioCodec != AudioCodecType_STAC9221)
378 rc = E_INVALIDARG;
379 break;
380 }
381
382 default:
383 AssertMsgFailed(("Wrong audio controller type %d\n",
384 mData->controllerType));
385 rc = E_FAIL;
386 }
387
388 if (!SUCCEEDED(rc))
389 return setError(rc,
390 tr("Invalid audio codec type %d"),
391 aAudioCodec);
392
393 if (mData->codecType != aAudioCodec)
394 {
395 mData.backup();
396 mData->codecType = aAudioCodec;
397 alock.release();
398 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
399 mParent->i_setModified(Machine::IsModified_AudioAdapter);
400 }
401
402 return rc;
403}
404
405HRESULT AudioAdapter::getPropertiesList(std::vector<com::Utf8Str>& aProperties)
406{
407 using namespace settings;
408
409 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
410
411 aProperties.resize(0);
412 StringsMap::const_iterator cit = mData->properties.begin();
413 while(cit != mData->properties.end())
414 {
415 Utf8Str key = cit->first;
416 aProperties.push_back(cit->first);
417 ++cit;
418 }
419
420 return S_OK;
421}
422
423HRESULT AudioAdapter::getProperty(const com::Utf8Str &aKey, com::Utf8Str &aValue)
424{
425 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
426
427 settings::StringsMap::const_iterator cit = mData->properties.find(aKey);
428 if (cit != mData->properties.end())
429 aValue = cit->second;
430
431 return S_OK;
432}
433
434HRESULT AudioAdapter::setProperty(const com::Utf8Str &aKey, const com::Utf8Str &aValue)
435{
436 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
437
438 /* Generic properties processing.
439 * Look up the old value first; if nothing's changed then do nothing.
440 */
441 Utf8Str strOldValue;
442
443 settings::StringsMap::const_iterator cit = mData->properties.find(aKey);
444 if (cit != mData->properties.end())
445 strOldValue = cit->second;
446
447 if (strOldValue != aValue)
448 {
449 if (aValue.isEmpty())
450 mData->properties.erase(aKey);
451 else
452 mData->properties[aKey] = aValue;
453 }
454
455 alock.release();
456
457 return S_OK;
458}
459
460// IAudioAdapter methods
461/////////////////////////////////////////////////////////////////////////////
462
463// public methods only for internal purposes
464/////////////////////////////////////////////////////////////////////////////
465
466/**
467 * Loads settings from the given machine node.
468 * May be called once right after this object creation.
469 *
470 * @param data Configuration settings.
471 *
472 * @note Locks this object for writing.
473 */
474HRESULT AudioAdapter::i_loadSettings(const settings::AudioAdapter &data)
475{
476 AutoCaller autoCaller(this);
477 AssertComRCReturnRC(autoCaller.rc());
478
479 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
480
481 /* Note: we assume that the default values for attributes of optional
482 * nodes are assigned in the Data::Data() constructor and don't do it
483 * here. It implies that this method may only be called after constructing
484 * a new AudioAdapter object while all its data fields are in the default
485 * values. Exceptions are fields whose creation time defaults don't match
486 * values that should be applied when these fields are not explicitly set
487 * in the settings file (for backwards compatibility reasons). This takes
488 * place when a setting of a newly created object must default to A while
489 * the same setting of an object loaded from the old settings file must
490 * default to B. */
491 mData.assignCopy(&data);
492
493 return S_OK;
494}
495
496/**
497 * Saves settings to the given machine node.
498 *
499 * @param data Configuration settings.
500 *
501 * @note Locks this object for reading.
502 */
503HRESULT AudioAdapter::i_saveSettings(settings::AudioAdapter &data)
504{
505 AutoCaller autoCaller(this);
506 AssertComRCReturnRC(autoCaller.rc());
507
508 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
509
510 data = *mData.data();
511
512 return S_OK;
513}
514
515/**
516 * @note Locks this object for writing.
517 */
518void AudioAdapter::i_rollback()
519{
520 /* sanity */
521 AutoCaller autoCaller(this);
522 AssertComRCReturnVoid(autoCaller.rc());
523
524 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
525
526 mData.rollback();
527}
528
529/**
530 * @note Locks this object for writing, together with the peer object (also
531 * for writing) if there is one.
532 */
533void AudioAdapter::i_commit()
534{
535 /* sanity */
536 AutoCaller autoCaller(this);
537 AssertComRCReturnVoid(autoCaller.rc());
538
539 /* sanity too */
540 AutoCaller peerCaller(mPeer);
541 AssertComRCReturnVoid(peerCaller.rc());
542
543 /* lock both for writing since we modify both (mPeer is "master" so locked
544 * first) */
545 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
546
547 if (mData.isBackedUp())
548 {
549 mData.commit();
550 if (mPeer)
551 {
552 /* attach new data to the peer and reshare it */
553 mPeer->mData.attach(mData);
554 }
555 }
556}
557
558/**
559 * @note Locks this object for writing, together with the peer object
560 * represented by @a aThat (locked for reading).
561 */
562void AudioAdapter::i_copyFrom(AudioAdapter *aThat)
563{
564 AssertReturnVoid(aThat != NULL);
565
566 /* sanity */
567 AutoCaller autoCaller(this);
568 AssertComRCReturnVoid(autoCaller.rc());
569
570 /* sanity too */
571 AutoCaller thatCaller(aThat);
572 AssertComRCReturnVoid(thatCaller.rc());
573
574 /* peer is not modified, lock it for reading (aThat is "master" so locked
575 * first) */
576 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
577 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
578
579 /* this will back up current data */
580 mData.assignCopy(aThat->mData);
581}
582/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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