VirtualBox

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

Last change on this file since 55528 was 55528, checked in by vboxsync, 10 years ago

Main/idl: added IAudioAdapter::enabledIn/enabledOut

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: AudioAdapterImpl.cpp 55528 2015-04-29 16:38:59Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2015 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. 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
30struct AudioAdapterData
31{
32 AudioAdapterData() :
33 mEnabled(false),
34 mAudioDriver(AudioDriverType_Null),
35 mAudioController(AudioControllerType_AC97)
36 {}
37
38 BOOL mEnabled;
39 AudioDriverType_T mAudioDriver;
40 AudioControllerType_T mAudioController;
41};
42
43struct AudioAdapter::Data
44{
45 Backupable<AudioAdapterData> m;
46};
47
48// constructor / destructor
49/////////////////////////////////////////////////////////////////////////////
50
51AudioAdapter::AudioAdapter()
52 : mParent(NULL),
53 mData(NULL)
54{
55}
56
57AudioAdapter::~AudioAdapter()
58{
59}
60
61HRESULT AudioAdapter::FinalConstruct()
62{
63 return BaseFinalConstruct();
64}
65
66void AudioAdapter::FinalRelease()
67{
68 uninit();
69 BaseFinalRelease();
70}
71
72// public initializer/uninitializer for internal purposes only
73/////////////////////////////////////////////////////////////////////////////
74
75/**
76 * Initializes the audio adapter object.
77 *
78 * @param aParent Handle of the parent object.
79 */
80HRESULT AudioAdapter::init (Machine *aParent)
81{
82 LogFlowThisFunc(("aParent=%p\n", aParent));
83
84 ComAssertRet(aParent, E_INVALIDARG);
85
86 /* Enclose the state transition NotReady->InInit->Ready */
87 AutoInitSpan autoInitSpan(this);
88 AssertReturn(autoInitSpan.isOk(), E_FAIL);
89
90 /* Get the default audio driver out of the system properties */
91 ComPtr<IVirtualBox> VBox;
92 HRESULT rc = aParent->COMGETTER(Parent)(VBox.asOutParam());
93 if (FAILED(rc)) return rc;
94 ComPtr<ISystemProperties> sysProps;
95 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
96 if (FAILED(rc)) return rc;
97 AudioDriverType_T defaultAudioDriver;
98 rc = sysProps->COMGETTER(DefaultAudioDriver)(&defaultAudioDriver);
99 if (FAILED(rc)) return rc;
100
101 unconst(mParent) = aParent;
102 /* mPeer is left null */
103
104 mData = new Data();
105 mData->m.allocate();
106 mData->m->mAudioDriver = defaultAudioDriver;
107
108 /* Confirm a successful initialization */
109 autoInitSpan.setSucceeded();
110
111 return S_OK;
112}
113
114/**
115 * Initializes the audio adapter object given another audio adapter object
116 * (a kind of copy constructor). This object shares data with
117 * the object passed as an argument.
118 *
119 * @note This object must be destroyed before the original object
120 * it shares data with is destroyed.
121 *
122 * @note Locks @a aThat object for reading.
123 */
124HRESULT AudioAdapter::init (Machine *aParent, AudioAdapter *aThat)
125{
126 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
127
128 ComAssertRet(aParent && aThat, E_INVALIDARG);
129
130 /* Enclose the state transition NotReady->InInit->Ready */
131 AutoInitSpan autoInitSpan(this);
132 AssertReturn(autoInitSpan.isOk(), E_FAIL);
133
134 unconst(mParent) = aParent;
135 unconst(mPeer) = aThat;
136
137 AutoCaller thatCaller (aThat);
138 AssertComRCReturnRC(thatCaller.rc());
139
140 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
141 mData = new Data();
142 mData->m.share (aThat->mData->m);
143
144 /* Confirm a successful initialization */
145 autoInitSpan.setSucceeded();
146
147 return S_OK;
148}
149
150/**
151 * Initializes the guest object given another guest object
152 * (a kind of copy constructor). This object makes a private copy of data
153 * of the original object passed as an argument.
154 *
155 * @note Locks @a aThat object for reading.
156 */
157HRESULT AudioAdapter::initCopy (Machine *aParent, AudioAdapter *aThat)
158{
159 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
160
161 ComAssertRet(aParent && aThat, E_INVALIDARG);
162
163 /* Enclose the state transition NotReady->InInit->Ready */
164 AutoInitSpan autoInitSpan(this);
165 AssertReturn(autoInitSpan.isOk(), E_FAIL);
166
167 unconst(mParent) = aParent;
168 /* mPeer is left null */
169
170 AutoCaller thatCaller (aThat);
171 AssertComRCReturnRC(thatCaller.rc());
172
173 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
174 mData = new Data();
175 mData->m.attachCopy (aThat->mData->m);
176
177 /* Confirm a successful initialization */
178 autoInitSpan.setSucceeded();
179
180 return S_OK;
181}
182
183/**
184 * Uninitializes the instance and sets the ready flag to FALSE.
185 * Called either from FinalRelease() or by the parent when it gets destroyed.
186 */
187void AudioAdapter::uninit()
188{
189 LogFlowThisFunc(("\n"));
190
191 /* Enclose the state transition Ready->InUninit->NotReady */
192 AutoUninitSpan autoUninitSpan(this);
193 if (autoUninitSpan.uninitDone())
194 return;
195
196 mData->m.free();
197 delete mData;
198 mData = NULL;
199
200 unconst(mPeer) = NULL;
201 unconst(mParent) = NULL;
202}
203
204// IAudioAdapter properties
205/////////////////////////////////////////////////////////////////////////////
206
207HRESULT AudioAdapter::getEnabled(BOOL *aEnabled)
208{
209 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
210
211 *aEnabled = mData->m->mEnabled;
212
213 return S_OK;
214}
215
216HRESULT AudioAdapter::setEnabled(BOOL aEnabled)
217{
218 /* the machine needs to be mutable */
219 AutoMutableStateDependency adep(mParent);
220 if (FAILED(adep.rc())) return adep.rc();
221
222 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
223
224 if (mData->m->mEnabled != aEnabled)
225 {
226 mData->m.backup();
227 mData->m->mEnabled = aEnabled;
228
229 alock.release();
230 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
231 mParent->i_setModified(Machine::IsModified_AudioAdapter);
232 }
233
234 return S_OK;
235}
236
237HRESULT AudioAdapter::getEnabledIn(BOOL *aEnabled)
238{
239 return E_NOTIMPL;
240}
241
242HRESULT AudioAdapter::setEnabledIn(BOOL aEnabled)
243{
244 return E_NOTIMPL;
245}
246
247HRESULT AudioAdapter::getEnabledOut(BOOL *aEnabled)
248{
249 return E_NOTIMPL;
250}
251
252HRESULT AudioAdapter::setEnabledOut(BOOL aEnabled)
253{
254 return E_NOTIMPL;
255}
256
257HRESULT AudioAdapter::getAudioDriver(AudioDriverType_T *aAudioDriver)
258{
259 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
260
261 *aAudioDriver = mData->m->mAudioDriver;
262
263 return S_OK;
264}
265
266HRESULT AudioAdapter::setAudioDriver(AudioDriverType_T aAudioDriver)
267{
268
269 /* the machine needs to be mutable */
270 AutoMutableOrSavedStateDependency adep(mParent);
271 if (FAILED(adep.rc())) return adep.rc();
272
273 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
274
275 HRESULT rc = S_OK;
276
277 if (mData->m->mAudioDriver != aAudioDriver)
278 {
279 if (settings::MachineConfigFile::isAudioDriverAllowedOnThisHost(aAudioDriver))
280 {
281 mData->m.backup();
282 mData->m->mAudioDriver = aAudioDriver;
283 alock.release();
284 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
285 mParent->i_setModified(Machine::IsModified_AudioAdapter);
286 }
287 else
288 {
289 AssertMsgFailed(("Wrong audio driver type %d\n", aAudioDriver));
290 rc = E_FAIL;
291 }
292 }
293
294 return rc;
295}
296
297HRESULT AudioAdapter::getAudioController(AudioControllerType_T *aAudioController)
298{
299 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
300
301 *aAudioController = mData->m->mAudioController;
302
303 return S_OK;
304}
305
306HRESULT AudioAdapter::setAudioController(AudioControllerType_T aAudioController)
307{
308 /* the machine needs to be mutable */
309 AutoMutableStateDependency adep(mParent);
310 if (FAILED(adep.rc())) return adep.rc();
311
312 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
313
314 HRESULT rc = S_OK;
315
316 if (mData->m->mAudioController != aAudioController)
317 {
318 /*
319 * which audio hardware type are we supposed to use?
320 */
321 switch (aAudioController)
322 {
323 case AudioControllerType_AC97:
324 case AudioControllerType_SB16:
325 case AudioControllerType_HDA:
326 {
327 mData->m.backup();
328 mData->m->mAudioController = aAudioController;
329 alock.release();
330 AutoWriteLock mlock(mParent COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
331 mParent->i_setModified(Machine::IsModified_AudioAdapter);
332 break;
333 }
334
335 default:
336 AssertMsgFailed (("Wrong audio controller type %d\n",
337 aAudioController));
338 rc = E_FAIL;
339 }
340 }
341
342 return rc;
343}
344
345// IAudioAdapter methods
346/////////////////////////////////////////////////////////////////////////////
347
348// public methods only for internal purposes
349/////////////////////////////////////////////////////////////////////////////
350
351/**
352 * Loads settings from the given machine node.
353 * May be called once right after this object creation.
354 *
355 * @param aMachineNode <Machine> node.
356 *
357 * @note Locks this object for writing.
358 */
359HRESULT AudioAdapter::i_loadSettings(const settings::AudioAdapter &data)
360{
361 AutoCaller autoCaller(this);
362 AssertComRCReturnRC(autoCaller.rc());
363
364 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
365
366 /* Note: we assume that the default values for attributes of optional
367 * nodes are assigned in the Data::Data() constructor and don't do it
368 * here. It implies that this method may only be called after constructing
369 * a new AudioAdapter object while all its data fields are in the default
370 * values. Exceptions are fields whose creation time defaults don't match
371 * values that should be applied when these fields are not explicitly set
372 * in the settings file (for backwards compatibility reasons). This takes
373 * place when a setting of a newly created object must default to A while
374 * the same setting of an object loaded from the old settings file must
375 * default to B. */
376
377 mData->m->mEnabled = data.fEnabled;
378 mData->m->mAudioController = data.controllerType;
379 mData->m->mAudioDriver = data.driverType;
380
381 return S_OK;
382}
383
384/**
385 * Saves settings to the given machine node.
386 *
387 * @param aMachineNode <Machine> node.
388 *
389 * @note Locks this object for reading.
390 */
391HRESULT AudioAdapter::i_saveSettings(settings::AudioAdapter &data)
392{
393 AutoCaller autoCaller(this);
394 AssertComRCReturnRC(autoCaller.rc());
395
396 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
397
398 data.fEnabled = !!mData->m->mEnabled;
399 data.controllerType = mData->m->mAudioController;
400 data.driverType = mData->m->mAudioDriver;
401 return S_OK;
402}
403
404/**
405 * @note Locks this object for writing.
406 */
407void AudioAdapter::i_rollback()
408{
409 /* sanity */
410 AutoCaller autoCaller(this);
411 AssertComRCReturnVoid(autoCaller.rc());
412
413 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
414
415 mData->m.rollback();
416}
417
418/**
419 * @note Locks this object for writing, together with the peer object (also
420 * for writing) if there is one.
421 */
422void AudioAdapter::i_commit()
423{
424 /* sanity */
425 AutoCaller autoCaller(this);
426 AssertComRCReturnVoid (autoCaller.rc());
427
428 /* sanity too */
429 AutoCaller peerCaller (mPeer);
430 AssertComRCReturnVoid (peerCaller.rc());
431
432 /* lock both for writing since we modify both (mPeer is "master" so locked
433 * first) */
434 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
435
436 if (mData->m.isBackedUp())
437 {
438 mData->m.commit();
439 if (mPeer)
440 {
441 /* attach new data to the peer and reshare it */
442 mPeer->mData->m.attach (mData->m);
443 }
444 }
445}
446
447/**
448 * @note Locks this object for writing, together with the peer object
449 * represented by @a aThat (locked for reading).
450 */
451void AudioAdapter::i_copyFrom(AudioAdapter *aThat)
452{
453 AssertReturnVoid (aThat != NULL);
454
455 /* sanity */
456 AutoCaller autoCaller(this);
457 AssertComRCReturnVoid (autoCaller.rc());
458
459 /* sanity too */
460 AutoCaller thatCaller (aThat);
461 AssertComRCReturnVoid (thatCaller.rc());
462
463 /* peer is not modified, lock it for reading (aThat is "master" so locked
464 * first) */
465 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
466 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
467
468 /* this will back up current data */
469 mData->m.assignCopy(aThat->mData->m);
470}
471/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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