VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/CaptureSettingsImpl.cpp@ 75313

Last change on this file since 75313 was 75308, checked in by vboxsync, 6 years ago

Build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
Line 
1/* $Id: CaptureSettingsImpl.cpp 75308 2018-11-07 14:20:59Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation - Machine capture settings.
5 */
6
7/*
8 * Copyright (C) 2018 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 "CaptureSettingsImpl.h"
20#include "CaptureScreenSettingsImpl.h"
21#include "MachineImpl.h"
22
23#include <iprt/cpp/utils.h>
24#include <VBox/settings.h>
25
26#include "AutoStateDep.h"
27#include "AutoCaller.h"
28#include "Global.h"
29#include "Logging.h"
30
31////////////////////////////////////////////////////////////////////////////////
32//
33// CaptureSettings private data definition
34//
35////////////////////////////////////////////////////////////////////////////////
36
37struct CaptureSettings::Data
38{
39 Data()
40 : pMachine(NULL)
41 { }
42
43 Machine * const pMachine;
44 ComObjPtr<CaptureSettings> pPeer;
45 CaptureScreenSettingsMap mapScreenSettings;
46 bool fHasMachineLock;
47
48 // use the XML settings structure in the members for simplicity
49 Backupable<settings::CaptureSettings> bd;
50};
51
52DEFINE_EMPTY_CTOR_DTOR(CaptureSettings)
53
54HRESULT CaptureSettings::FinalConstruct()
55{
56 return BaseFinalConstruct();
57}
58
59void CaptureSettings::FinalRelease()
60{
61 uninit();
62 BaseFinalRelease();
63}
64
65/**
66 * Initializes the audio adapter object.
67 *
68 * @returns COM result indicator
69 */
70HRESULT CaptureSettings::init(Machine *aParent)
71{
72 LogFlowThisFuncEnter();
73 LogFlowThisFunc(("aParent: %p\n", aParent));
74
75 ComAssertRet(aParent, E_INVALIDARG);
76
77 /* Enclose the state transition NotReady->InInit->Ready */
78 AutoInitSpan autoInitSpan(this);
79 AssertReturn(autoInitSpan.isOk(), E_FAIL);
80
81 m = new Data();
82
83 /* share the parent weakly */
84 unconst(m->pMachine) = aParent;
85
86 m->bd.allocate();
87 m->fHasMachineLock = false;
88
89 autoInitSpan.setSucceeded();
90
91 LogFlowThisFuncLeave();
92 return S_OK;
93}
94
95/**
96 * Initializes the capture settings object given another capture settings 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 */
103HRESULT CaptureSettings::init(Machine *aParent, CaptureSettings *that)
104{
105 LogFlowThisFuncEnter();
106 LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
107
108 ComAssertRet(aParent && that, E_INVALIDARG);
109
110 /* Enclose the state transition NotReady->InInit->Ready */
111 AutoInitSpan autoInitSpan(this);
112 AssertReturn(autoInitSpan.isOk(), E_FAIL);
113
114 m = new Data();
115
116 unconst(m->pMachine) = aParent;
117 m->pPeer = that;
118
119 AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
120
121 m->bd.share(that->m->bd);
122 m->mapScreenSettings = that->m->mapScreenSettings;
123 m->fHasMachineLock = false;
124
125 autoInitSpan.setSucceeded();
126
127 LogFlowThisFuncLeave();
128 return S_OK;
129}
130
131/**
132 * Initializes the guest object given another guest object
133 * (a kind of copy constructor). This object makes a private copy of data
134 * of the original object passed as an argument.
135 */
136HRESULT CaptureSettings::initCopy(Machine *aParent, CaptureSettings *that)
137{
138 LogFlowThisFuncEnter();
139 LogFlowThisFunc(("aParent: %p, that: %p\n", aParent, that));
140
141 ComAssertRet(aParent && that, E_INVALIDARG);
142
143 /* Enclose the state transition NotReady->InInit->Ready */
144 AutoInitSpan autoInitSpan(this);
145 AssertReturn(autoInitSpan.isOk(), E_FAIL);
146
147 m = new Data();
148
149 unconst(m->pMachine) = aParent;
150 // mPeer is left null
151
152 AutoWriteLock thatlock(that COMMA_LOCKVAL_SRC_POS);
153
154 m->bd.attachCopy(that->m->bd);
155 m->mapScreenSettings = that->m->mapScreenSettings;
156 m->fHasMachineLock = false;
157
158 autoInitSpan.setSucceeded();
159
160 LogFlowThisFuncLeave();
161 return S_OK;
162}
163
164/**
165 * Uninitializes the instance and sets the ready flag to FALSE.
166 * Called either from FinalRelease() or by the parent when it gets destroyed.
167 */
168void CaptureSettings::uninit()
169{
170 LogFlowThisFuncEnter();
171
172 /* Enclose the state transition Ready->InUninit->NotReady */
173 AutoUninitSpan autoUninitSpan(this);
174 if (autoUninitSpan.uninitDone())
175 return;
176
177 m->bd.free();
178
179 unconst(m->pPeer) = NULL;
180 unconst(m->pMachine) = NULL;
181
182 delete m;
183 m = NULL;
184
185 LogFlowThisFuncLeave();
186}
187
188// ICaptureSettings properties
189/////////////////////////////////////////////////////////////////////////////
190
191HRESULT CaptureSettings::getEnabled(BOOL *enabled)
192{
193 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
194
195 *enabled = m->bd->fEnabled;
196
197 return S_OK;
198}
199
200HRESULT CaptureSettings::setEnabled(BOOL enable)
201{
202 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
203
204 const bool fEnabled = RT_BOOL(enable);
205
206 HRESULT rc = S_OK;
207
208 if (m->bd->fEnabled != fEnabled)
209 {
210 m->bd.backup();
211 m->bd->fEnabled = fEnabled;
212
213 alock.release();
214 rc = m->pMachine->i_onCaptureChange();
215 if (FAILED(rc))
216 {
217 /*
218 * Normally we would do the actual change _after_ i_onCaptureChange() succeeded.
219 * We cannot do this because that function uses CaptureSettings::GetEnabled to
220 * determine if it should start or stop capturing. Therefore we need to manually
221 * undo change.
222 */
223 alock.acquire();
224 m->bd->fEnabled = m->bd.backedUpData()->fEnabled;
225 return rc;
226 }
227 else
228 {
229 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking
230 m->pMachine->i_setModified(Machine::IsModified_Capture);
231
232 /* We need to indicate here that we just took the machine lock, as Machine::i_saveSettings() will
233 * call i_commit(), which in turn also wants to lock the machine for writing. */
234 m->fHasMachineLock = true;
235
236 /** Save settings if online - @todo why is this required? -- @bugref{6818} */
237 if (Global::IsOnline(m->pMachine->i_getMachineState()))
238 rc = m->pMachine->i_saveSettings(NULL);
239
240 m->fHasMachineLock = false;
241 }
242 }
243
244 return rc;
245}
246
247HRESULT CaptureSettings::getScreens(std::vector<ComPtr<ICaptureScreenSettings> > &aCaptureScreenSettings)
248{
249 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
250
251 aCaptureScreenSettings.clear();
252 aCaptureScreenSettings.resize(m->mapScreenSettings.size());
253
254 CaptureScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenSettings.begin();
255 size_t i = 0;
256 while (itScreenSettings != m->mapScreenSettings.end())
257 {
258 itScreenSettings->second.queryInterfaceTo(aCaptureScreenSettings[i].asOutParam());
259 Assert(aCaptureScreenSettings[i].isNotNull());
260 ++i;
261 ++itScreenSettings;
262 }
263
264 Assert(aCaptureScreenSettings.size() == m->mapScreenSettings.size());
265
266 return S_OK;
267}
268
269HRESULT CaptureSettings::getScreenSettings(ULONG uScreenId, ComPtr<ICaptureScreenSettings> &aCaptureScreenSettings)
270{
271 if (uScreenId + 1 > m->mapScreenSettings.size())
272 return setError(E_INVALIDARG, tr("Invalid screen ID specified"));
273
274 CaptureScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenSettings.find(uScreenId);
275 if (itScreenSettings != m->mapScreenSettings.end())
276 {
277 itScreenSettings->second.queryInterfaceTo(aCaptureScreenSettings.asOutParam());
278 return S_OK;
279 }
280
281 return VBOX_E_OBJECT_NOT_FOUND;
282}
283
284// ICaptureSettings methods
285/////////////////////////////////////////////////////////////////////////////
286
287// public methods only for internal purposes
288/////////////////////////////////////////////////////////////////////////////
289
290/**
291 * Adds a screen settings object to the recording settings.
292 *
293 * @returns IPRT status code. VERR_ALREADY_EXISTS if the object in question already exists.
294 * @param uScreenId Screen ID to add settings for.
295 * @param data Recording screen settings to use for that screen.
296 */
297int CaptureSettings::i_addScreen(uint32_t uScreenId, const settings::CaptureScreenSettings &data)
298{
299 if (m->mapScreenSettings.find(uScreenId) != m->mapScreenSettings.end())
300 {
301 AssertFailed();
302 return VERR_ALREADY_EXISTS;
303 }
304
305 int vrc = VINF_SUCCESS;
306
307 ComObjPtr<CaptureScreenSettings> captureScreenSettings;
308 HRESULT rc = captureScreenSettings.createObject();
309 if (SUCCEEDED(rc))
310 {
311 rc = captureScreenSettings->init(m->pMachine, uScreenId, data);
312 if (SUCCEEDED(rc))
313 {
314 try
315 {
316 m->mapScreenSettings[uScreenId] = captureScreenSettings;
317 }
318 catch (std::bad_alloc &)
319 {
320 vrc = VERR_NO_MEMORY;
321 }
322 }
323 }
324
325 return vrc;
326}
327
328/**
329 * Loads settings from the given settings.
330 * May be called once right after this object creation.
331 *
332 * @param data Capture settings to load from.
333 *
334 * @note Locks this object for writing.
335 */
336HRESULT CaptureSettings::i_loadSettings(const settings::CaptureSettings &data)
337{
338 AutoCaller autoCaller(this);
339 AssertComRCReturnRC(autoCaller.rc());
340
341 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
342
343 HRESULT rc = S_OK;
344
345 m->mapScreenSettings.clear();
346
347 settings::CaptureScreenMap::const_iterator itScreen = data.mapScreens.begin();
348 while (itScreen != data.mapScreens.end())
349 {
350 int vrc = i_addScreen(itScreen->first /* uScreenId */, itScreen->second /* Settings */);
351 if (RT_FAILURE(vrc))
352 {
353 rc = E_OUTOFMEMORY;
354 break;
355 }
356
357 ++itScreen;
358 }
359
360 if (FAILED(rc))
361 return rc;
362
363 ComAssertComRC(rc);
364 Assert(m->mapScreenSettings.size() == data.mapScreens.size());
365
366 // simply copy
367 m->bd.assignCopy(&data);
368
369 return rc;
370}
371
372/**
373 * Saves settings to the given settings.
374 *
375 * @param data Where to store the capture settings to.
376 *
377 * @note Locks this object for reading.
378 */
379HRESULT CaptureSettings::i_saveSettings(settings::CaptureSettings &data)
380{
381 AutoCaller autoCaller(this);
382 AssertComRCReturnRC(autoCaller.rc());
383
384 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
385
386 data = *m->bd.data();
387
388 settings::CaptureScreenMap::iterator itScreen = data.mapScreens.begin();
389 while (itScreen != data.mapScreens.end())
390 {
391 /* Store relative path of capture file if possible. */
392 m->pMachine->i_copyPathRelativeToMachine(itScreen->second.File.strName /* Source */,
393 itScreen->second.File.strName /* Target */);
394 ++itScreen;
395 }
396
397 return S_OK;
398}
399
400void CaptureSettings::i_rollback()
401{
402 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
403 m->bd.rollback();
404}
405
406void CaptureSettings::i_commit()
407{
408 /* sanity */
409 AutoCaller autoCaller(this);
410 AssertComRCReturnVoid(autoCaller.rc());
411
412 /* sanity too */
413 AutoCaller peerCaller(m->pPeer);
414 AssertComRCReturnVoid(peerCaller.rc());
415
416 /* lock both for writing since we modify both (mPeer is "master" so locked
417 * first) */
418 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
419
420 if (m->bd.isBackedUp())
421 {
422 m->bd.commit();
423 if (m->pPeer)
424 {
425 /* attach new data to the peer and reshare it */
426 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
427 m->pPeer->m->bd.attach(m->bd);
428 }
429 }
430}
431
432void CaptureSettings::i_copyFrom(CaptureSettings *aThat)
433{
434 AssertReturnVoid(aThat != NULL);
435
436 /* sanity */
437 AutoCaller autoCaller(this);
438 AssertComRCReturnVoid(autoCaller.rc());
439
440 /* sanity too */
441 AutoCaller thatCaller(aThat);
442 AssertComRCReturnVoid(thatCaller.rc());
443
444 /* peer is not modified, lock it for reading (aThat is "master" so locked
445 * first) */
446 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
447 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
448
449 /* this will back up current data */
450 m->bd.assignCopy(aThat->m->bd);
451}
452
453void CaptureSettings::i_applyDefaults(void)
454{
455 /* sanity */
456 AutoCaller autoCaller(this);
457 AssertComRCReturnVoid(autoCaller.rc());
458
459 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
460
461 /* Initialize default capturing settings here. */
462}
463
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