VirtualBox

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

Last change on this file since 75267 was 75264, checked in by vboxsync, 6 years ago

Capturing: SCM fixes.

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