VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/RecordingScreenSettingsImpl.cpp@ 97698

Last change on this file since 97698 was 96545, checked in by vboxsync, 2 years ago

Recording/Main: Made recording file name construction more deterministic (also required for testcase handling in Validation Kit), by only letting the recording screen settings to construct + alter the actual file name(s). ​bugref:10275

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.8 KB
Line 
1/* $Id: RecordingScreenSettingsImpl.cpp 96545 2022-08-29 17:41:05Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation - Recording settings of one virtual screen.
5 */
6
7/*
8 * Copyright (C) 2018-2022 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * SPDX-License-Identifier: GPL-3.0-only
27 */
28
29#define LOG_GROUP LOG_GROUP_MAIN_RECORDINGSCREENSETTINGS
30#include "LoggingNew.h"
31
32#include "RecordingScreenSettingsImpl.h"
33#include "RecordingSettingsImpl.h"
34#include "MachineImpl.h"
35
36#include <iprt/asm.h> /* For ASMAtomicXXX. */
37#include <iprt/path.h>
38#include <iprt/cpp/utils.h>
39#include <VBox/settings.h>
40
41#include "AutoStateDep.h"
42#include "AutoCaller.h"
43#include "Global.h"
44
45////////////////////////////////////////////////////////////////////////////////
46//
47// RecordScreenSettings private data definition
48//
49////////////////////////////////////////////////////////////////////////////////
50
51struct RecordingScreenSettings::Data
52{
53 Data()
54 : pParent(NULL)
55 , cRefs(0)
56 { }
57
58 RecordingSettings * const pParent;
59 const ComObjPtr<RecordingScreenSettings> pPeer;
60 uint32_t uScreenId;
61 /** Internal reference count to track sharing of this screen settings object among
62 * other recording settings objects. */
63 int32_t cRefs;
64
65 // use the XML settings structure in the members for simplicity
66 Backupable<settings::RecordingScreenSettings> bd;
67};
68
69// constructor / destructor
70////////////////////////////////////////////////////////////////////////////////
71
72DEFINE_EMPTY_CTOR_DTOR(RecordingScreenSettings)
73
74HRESULT RecordingScreenSettings::FinalConstruct()
75{
76 return BaseFinalConstruct();
77}
78
79void RecordingScreenSettings::FinalRelease()
80{
81 uninit();
82 BaseFinalRelease();
83}
84
85// public initializer/uninitializer for internal purposes only
86////////////////////////////////////////////////////////////////////////////////
87
88/**
89 * Initializes the recording screen settings object.
90 *
91 * @returns COM result indicator
92 */
93HRESULT RecordingScreenSettings::init(RecordingSettings *aParent, uint32_t uScreenId,
94 const settings::RecordingScreenSettings& aThat)
95{
96 LogFlowThisFunc(("aParent: %p\n", aParent));
97
98 ComAssertRet(aParent, E_INVALIDARG);
99
100 /* Enclose the state transition NotReady->InInit->Ready */
101 AutoInitSpan autoInitSpan(this);
102 AssertReturn(autoInitSpan.isOk(), E_FAIL);
103
104 m = new Data();
105
106 /* Share the parent & machine weakly. */
107 unconst(m->pParent) = aParent;
108 /* mPeer is left null. */
109
110 /* Simply copy the settings data. */
111 m->uScreenId = uScreenId;
112 m->bd.allocate();
113 m->bd->operator=(aThat);
114
115 HRESULT hrc = S_OK;
116
117 int vrc = i_initInternal();
118 if (RT_SUCCESS(vrc))
119 {
120 autoInitSpan.setSucceeded();
121 }
122 else
123 {
124 autoInitSpan.setFailed();
125 hrc = E_UNEXPECTED;
126 }
127
128 LogFlowThisFuncLeave();
129 return hrc;
130}
131
132/**
133 * Initializes the recording settings object given another recording settings object
134 * (a kind of copy constructor). This object shares data with
135 * the object passed as an argument.
136 *
137 * @note This object must be destroyed before the original object
138 * it shares data with is destroyed.
139 */
140HRESULT RecordingScreenSettings::init(RecordingSettings *aParent, RecordingScreenSettings *aThat)
141{
142 LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
143
144 ComAssertRet(aParent && aThat, E_INVALIDARG);
145
146 /* Enclose the state transition NotReady->InInit->Ready */
147 AutoInitSpan autoInitSpan(this);
148 AssertReturn(autoInitSpan.isOk(), E_FAIL);
149
150 m = new Data();
151
152 unconst(m->pParent) = aParent;
153 unconst(m->pPeer) = aThat;
154
155 AutoCaller thatCaller(aThat);
156 AssertComRCReturnRC(thatCaller.rc());
157
158 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
159
160 m->uScreenId = aThat->m->uScreenId;
161 m->bd.share(aThat->m->bd);
162
163 HRESULT hrc = S_OK;
164
165 int vrc = i_initInternal();
166 if (RT_SUCCESS(vrc))
167 {
168 autoInitSpan.setSucceeded();
169 }
170 else
171 {
172 autoInitSpan.setFailed();
173 hrc = E_UNEXPECTED;
174 }
175
176 LogFlowThisFuncLeave();
177 return hrc;
178}
179
180/**
181 * Initializes the guest object given another guest object
182 * (a kind of copy constructor). This object makes a private copy of data
183 * of the original object passed as an argument.
184 */
185HRESULT RecordingScreenSettings::initCopy(RecordingSettings *aParent, RecordingScreenSettings *aThat)
186{
187 LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
188
189 ComAssertRet(aParent && aThat, E_INVALIDARG);
190
191 /* Enclose the state transition NotReady->InInit->Ready */
192 AutoInitSpan autoInitSpan(this);
193 AssertReturn(autoInitSpan.isOk(), E_FAIL);
194
195 m = new Data();
196
197 unconst(m->pParent) = aParent;
198 /* mPeer is left null. */
199
200 AutoCaller thatCaller(aThat);
201 AssertComRCReturnRC(thatCaller.rc());
202
203 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
204
205 m->uScreenId = aThat->m->uScreenId;
206 m->bd.attachCopy(aThat->m->bd);
207
208 HRESULT hrc = S_OK;
209
210 int vrc = i_initInternal();
211 if (RT_SUCCESS(vrc))
212 {
213 autoInitSpan.setSucceeded();
214 }
215 else
216 {
217 autoInitSpan.setFailed();
218 hrc = E_UNEXPECTED;
219 }
220
221 LogFlowThisFuncLeave();
222 return hrc;
223}
224
225/**
226 * Uninitializes the instance and sets the ready flag to FALSE.
227 * Called either from FinalRelease() or by the parent when it gets destroyed.
228 */
229void RecordingScreenSettings::uninit()
230{
231 LogThisFunc(("%p\n", this));
232
233 /* Enclose the state transition Ready->InUninit->NotReady */
234 AutoUninitSpan autoUninitSpan(this);
235 if (autoUninitSpan.uninitDone())
236 return;
237
238 /* Make sure nobody holds an internal reference to it anymore. */
239 AssertReturnVoid(m->cRefs == 0);
240
241 m->bd.free();
242
243 unconst(m->pPeer) = NULL;
244 unconst(m->pParent) = NULL;
245
246 delete m;
247 m = NULL;
248
249 LogFlowThisFuncLeave();
250}
251
252HRESULT RecordingScreenSettings::isFeatureEnabled(RecordingFeature_T aFeature, BOOL *aEnabled)
253{
254 AutoCaller autoCaller(this);
255 if (FAILED(autoCaller.rc())) return autoCaller.rc();
256
257 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
258
259 settings::RecordingFeatureMap::const_iterator itFeature = m->bd->featureMap.find(aFeature);
260
261 *aEnabled = ( itFeature != m->bd->featureMap.end()
262 && itFeature->second == true);
263
264 return S_OK;
265}
266
267HRESULT RecordingScreenSettings::getId(ULONG *id)
268{
269 AutoCaller autoCaller(this);
270 if (FAILED(autoCaller.rc())) return autoCaller.rc();
271
272 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
273
274 *id = m->uScreenId;
275
276 return S_OK;
277}
278
279HRESULT RecordingScreenSettings::getEnabled(BOOL *enabled)
280{
281 AutoCaller autoCaller(this);
282 if (FAILED(autoCaller.rc())) return autoCaller.rc();
283
284 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
285
286 *enabled = m->bd->fEnabled ? TRUE : FALSE;
287
288 return S_OK;
289}
290
291HRESULT RecordingScreenSettings::setEnabled(BOOL enabled)
292{
293 AutoCaller autoCaller(this);
294 if (FAILED(autoCaller.rc())) return autoCaller.rc();
295
296 LogFlowThisFunc(("Screen %RU32\n", m->uScreenId));
297
298 if (!m->pParent->i_canChangeSettings())
299 return setError(E_INVALIDARG, tr("Cannot change enabled state of screen while recording is enabled"));
300
301 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
302
303 if (m->bd->fEnabled != RT_BOOL(enabled))
304 {
305 m->bd.backup();
306 m->bd->fEnabled = RT_BOOL(enabled);
307 alock.release();
308
309 m->pParent->i_onSettingsChanged();
310 }
311
312 LogFlowThisFunc(("Screen %RU32\n", m->uScreenId));
313 return S_OK;
314}
315
316HRESULT RecordingScreenSettings::getFeatures(std::vector<RecordingFeature_T> &aFeatures)
317{
318 AutoCaller autoCaller(this);
319 if (FAILED(autoCaller.rc())) return autoCaller.rc();
320
321 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
322
323 aFeatures.clear();
324
325 settings::RecordingFeatureMap::const_iterator itFeature = m->bd->featureMap.begin();
326 while (itFeature != m->bd->featureMap.end())
327 {
328 if (itFeature->second) /* Is feature enable? */
329 aFeatures.push_back(itFeature->first);
330
331 ++itFeature;
332 }
333
334 return S_OK;
335}
336
337HRESULT RecordingScreenSettings::setFeatures(const std::vector<RecordingFeature_T> &aFeatures)
338{
339 AutoCaller autoCaller(this);
340 if (FAILED(autoCaller.rc())) return autoCaller.rc();
341
342 if (!m->pParent->i_canChangeSettings())
343 return setError(E_INVALIDARG, tr("Cannot change features while recording is enabled"));
344
345 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
346
347 m->bd.backup();
348
349 settings::RecordingFeatureMap featureMapOld = m->bd->featureMap;
350 m->bd->featureMap.clear();
351
352 for (size_t i = 0; i < aFeatures.size(); i++)
353 {
354 switch (aFeatures[i])
355 {
356 case RecordingFeature_Audio:
357 m->bd->featureMap[RecordingFeature_Audio] = true;
358 break;
359
360 case RecordingFeature_Video:
361 m->bd->featureMap[RecordingFeature_Video] = true;
362 break;
363
364 default:
365 break;
366 }
367 }
368
369 if (m->bd->featureMap != featureMapOld)
370 {
371 alock.release();
372
373 m->pParent->i_onSettingsChanged();
374 }
375
376 return S_OK;
377}
378
379HRESULT RecordingScreenSettings::getDestination(RecordingDestination_T *aDestination)
380{
381 AutoCaller autoCaller(this);
382 if (FAILED(autoCaller.rc())) return autoCaller.rc();
383
384 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
385
386 *aDestination = m->bd->enmDest;
387
388 return S_OK;
389}
390
391HRESULT RecordingScreenSettings::setDestination(RecordingDestination_T aDestination)
392{
393 AutoCaller autoCaller(this);
394 if (FAILED(autoCaller.rc())) return autoCaller.rc();
395
396 if (!m->pParent->i_canChangeSettings())
397 return setError(E_INVALIDARG, tr("Cannot change destination type while recording is enabled"));
398
399 if (aDestination != RecordingDestination_File)
400 return setError(E_INVALIDARG, tr("Destination type invalid / not supported"));
401
402 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
403
404 if (m->bd->enmDest != aDestination)
405 {
406 m->bd.backup();
407 m->bd->enmDest = aDestination;
408
409 m->pParent->i_onSettingsChanged();
410 }
411
412 return S_OK;
413}
414
415HRESULT RecordingScreenSettings::getFilename(com::Utf8Str &aFilename)
416{
417 AutoCaller autoCaller(this);
418 if (FAILED(autoCaller.rc())) return autoCaller.rc();
419
420 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
421
422 /* Get default file name if an empty string or a single "." is set. */
423 if ( m->bd->File.strName.isEmpty()
424 || m->bd->File.strName.equals("."))
425 {
426 int vrc = m->pParent->i_getDefaultFilename(aFilename, m->uScreenId, true /* fWithFileExtension */);
427 if (RT_FAILURE(vrc))
428 return setErrorBoth(E_INVALIDARG, vrc, tr("Error retrieving default file name"));
429
430 /* Important: Don't assign the default file name to File.strName, as this woulnd't be considered
431 * as default settings anymore! */
432 }
433 else /* Return custom file name. */
434 aFilename = m->bd->File.strName;
435
436 return S_OK;
437}
438
439HRESULT RecordingScreenSettings::setFilename(const com::Utf8Str &aFilename)
440{
441 AutoCaller autoCaller(this);
442 if (FAILED(autoCaller.rc())) return autoCaller.rc();
443
444 if (!m->pParent->i_canChangeSettings())
445 return setError(E_INVALIDARG, tr("Cannot change file name while recording is enabled"));
446
447 if (aFilename.isNotEmpty())
448 {
449 if (!RTPathStartsWithRoot(aFilename.c_str()))
450 return setError(E_INVALIDARG, tr("Recording file name '%s' is not absolute"), aFilename.c_str());
451 }
452
453 /** @todo Add more sanity? */
454
455 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
456
457 /* Note: When setting an empty file name, this will return the screen's default file name when using ::getFileName(). */
458 if (m->bd->File.strName != aFilename)
459 {
460 Utf8Str strName;
461 int vrc = m->pParent->i_getFilename(strName, m->uScreenId, aFilename);
462 if (RT_SUCCESS(vrc))
463 {
464 m->bd.backup();
465 m->bd->File.strName = strName;
466
467 alock.release();
468
469 m->pParent->i_onSettingsChanged();
470 }
471 else
472 return setErrorBoth(E_ACCESSDENIED, vrc, tr("Could not set file name for recording screen"));
473 }
474
475 return S_OK;
476}
477
478HRESULT RecordingScreenSettings::getMaxTime(ULONG *aMaxTimeS)
479{
480 AutoCaller autoCaller(this);
481 if (FAILED(autoCaller.rc())) return autoCaller.rc();
482
483 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
484
485 *aMaxTimeS = m->bd->ulMaxTimeS;
486
487 return S_OK;
488}
489
490HRESULT RecordingScreenSettings::setMaxTime(ULONG aMaxTimeS)
491{
492 AutoCaller autoCaller(this);
493 if (FAILED(autoCaller.rc())) return autoCaller.rc();
494
495 if (!m->pParent->i_canChangeSettings())
496 return setError(E_INVALIDARG, tr("Cannot change maximum time while recording is enabled"));
497
498 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
499
500 if (m->bd->ulMaxTimeS != aMaxTimeS)
501 {
502 m->bd.backup();
503 m->bd->ulMaxTimeS = aMaxTimeS;
504
505 alock.release();
506
507 m->pParent->i_onSettingsChanged();
508 }
509
510 return S_OK;
511}
512
513HRESULT RecordingScreenSettings::getMaxFileSize(ULONG *aMaxFileSizeMB)
514{
515 AutoCaller autoCaller(this);
516 if (FAILED(autoCaller.rc())) return autoCaller.rc();
517
518 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
519
520 *aMaxFileSizeMB = m->bd->File.ulMaxSizeMB;
521
522 return S_OK;
523}
524
525HRESULT RecordingScreenSettings::setMaxFileSize(ULONG aMaxFileSize)
526{
527 AutoCaller autoCaller(this);
528 if (FAILED(autoCaller.rc())) return autoCaller.rc();
529
530 if (!m->pParent->i_canChangeSettings())
531 return setError(E_INVALIDARG, tr("Cannot change maximum file size while recording is enabled"));
532
533 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
534
535 if (m->bd->File.ulMaxSizeMB != aMaxFileSize)
536 {
537 m->bd.backup();
538 m->bd->File.ulMaxSizeMB = aMaxFileSize;
539
540 alock.release();
541
542 m->pParent->i_onSettingsChanged();
543 }
544
545 return S_OK;
546}
547
548HRESULT RecordingScreenSettings::getOptions(com::Utf8Str &aOptions)
549{
550 AutoCaller autoCaller(this);
551 if (FAILED(autoCaller.rc())) return autoCaller.rc();
552
553 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
554
555 aOptions = m->bd->strOptions;
556
557 return S_OK;
558}
559
560HRESULT RecordingScreenSettings::setOptions(const com::Utf8Str &aOptions)
561{
562 AutoCaller autoCaller(this);
563 if (FAILED(autoCaller.rc())) return autoCaller.rc();
564
565 if (!m->pParent->i_canChangeSettings())
566 return setError(E_INVALIDARG, tr("Cannot change options while recording is enabled"));
567
568 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
569
570 /* Note: Parsing and validation is done at codec level. */
571
572 m->bd.backup();
573 m->bd->strOptions = aOptions;
574
575 alock.release();
576
577 m->pParent->i_onSettingsChanged();
578
579 return S_OK;
580}
581
582HRESULT RecordingScreenSettings::getAudioCodec(RecordingAudioCodec_T *aCodec)
583{
584 AutoCaller autoCaller(this);
585 if (FAILED(autoCaller.rc())) return autoCaller.rc();
586
587 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
588
589 *aCodec = m->bd->Audio.enmCodec;
590
591 return S_OK;
592}
593
594HRESULT RecordingScreenSettings::setAudioCodec(RecordingAudioCodec_T aCodec)
595{
596 AutoCaller autoCaller(this);
597 if (FAILED(autoCaller.rc())) return autoCaller.rc();
598
599 if (!m->pParent->i_canChangeSettings())
600 return setError(E_INVALIDARG, tr("Cannot change audio codec while recording is enabled"));
601
602 if (aCodec != RecordingAudioCodec_OggVorbis)
603 return setError(E_INVALIDARG, tr("Audio codec not supported"));
604
605 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
606
607 if (m->bd->Audio.enmCodec != aCodec)
608 {
609 m->bd.backup();
610 m->bd->Audio.enmCodec = aCodec;
611
612 alock.release();
613
614 m->pParent->i_onSettingsChanged();
615 }
616
617 return S_OK;
618}
619
620HRESULT RecordingScreenSettings::getAudioDeadline(RecordingCodecDeadline_T *aDeadline)
621{
622 AutoCaller autoCaller(this);
623 if (FAILED(autoCaller.rc())) return autoCaller.rc();
624
625 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
626
627 *aDeadline = m->bd->Audio.enmDeadline;
628
629 return S_OK;
630}
631
632HRESULT RecordingScreenSettings::setAudioDeadline(RecordingCodecDeadline_T aDeadline)
633{
634 AutoCaller autoCaller(this);
635 if (FAILED(autoCaller.rc())) return autoCaller.rc();
636
637 if (!m->pParent->i_canChangeSettings())
638 return setError(E_INVALIDARG, tr("Cannot change audio deadline while recording is enabled"));
639
640 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
641
642 if (m->bd->Audio.enmDeadline != aDeadline)
643 {
644 m->bd.backup();
645 m->bd->Audio.enmDeadline = aDeadline;
646
647 alock.release();
648
649 m->pParent->i_onSettingsChanged();
650 }
651
652 return S_OK;
653}
654
655HRESULT RecordingScreenSettings::getAudioRateControlMode(RecordingRateControlMode_T *aMode)
656{
657 AutoCaller autoCaller(this);
658 if (FAILED(autoCaller.rc())) return autoCaller.rc();
659
660 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
661
662 *aMode = RecordingRateControlMode_VBR; /** @todo Implement CBR. */
663
664 return S_OK;
665}
666
667HRESULT RecordingScreenSettings::setAudioRateControlMode(RecordingRateControlMode_T aMode)
668{
669 AutoCaller autoCaller(this);
670 if (FAILED(autoCaller.rc())) return autoCaller.rc();
671
672 if (!m->pParent->i_canChangeSettings())
673 return setError(E_INVALIDARG, tr("Cannot change audio rate control mode while recording is enabled"));
674
675 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
676
677 /** @todo Implement this. */
678 RT_NOREF(aMode);
679
680 return E_NOTIMPL;
681}
682
683HRESULT RecordingScreenSettings::getAudioHz(ULONG *aHz)
684{
685 AutoCaller autoCaller(this);
686 if (FAILED(autoCaller.rc())) return autoCaller.rc();
687
688 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
689
690 *aHz = m->bd->Audio.uHz;
691
692 return S_OK;
693}
694
695HRESULT RecordingScreenSettings::setAudioHz(ULONG aHz)
696{
697 AutoCaller autoCaller(this);
698 if (FAILED(autoCaller.rc())) return autoCaller.rc();
699
700 if (!m->pParent->i_canChangeSettings())
701 return setError(E_INVALIDARG, tr("Cannot change audio Hertz rate while recording is enabled"));
702
703 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
704
705 if (m->bd->Audio.uHz != (uint16_t)aHz)
706 {
707 m->bd.backup();
708 m->bd->Audio.uHz = (uint16_t)aHz;
709
710 alock.release();
711
712 m->pParent->i_onSettingsChanged();
713 }
714
715 return S_OK;
716}
717
718HRESULT RecordingScreenSettings::getAudioBits(ULONG *aBits)
719{
720 AutoCaller autoCaller(this);
721 if (FAILED(autoCaller.rc())) return autoCaller.rc();
722
723 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
724
725 *aBits = m->bd->Audio.cBits;
726
727 return S_OK;
728}
729
730HRESULT RecordingScreenSettings::setAudioBits(ULONG aBits)
731{
732 AutoCaller autoCaller(this);
733 if (FAILED(autoCaller.rc())) return autoCaller.rc();
734
735 if (!m->pParent->i_canChangeSettings())
736 return setError(E_INVALIDARG, tr("Cannot change audio bits while recording is enabled"));
737
738 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
739
740 if (m->bd->Audio.cBits != (uint8_t)aBits)
741 {
742 m->bd.backup();
743 m->bd->Audio.cBits = (uint8_t)aBits;
744
745 alock.release();
746
747 m->pParent->i_onSettingsChanged();
748 }
749
750 return S_OK;
751}
752
753HRESULT RecordingScreenSettings::getAudioChannels(ULONG *aChannels)
754{
755 AutoCaller autoCaller(this);
756 if (FAILED(autoCaller.rc())) return autoCaller.rc();
757
758 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
759
760 *aChannels = m->bd->Audio.cChannels;
761
762 return S_OK;
763}
764
765HRESULT RecordingScreenSettings::setAudioChannels(ULONG aChannels)
766{
767 AutoCaller autoCaller(this);
768 if (FAILED(autoCaller.rc())) return autoCaller.rc();
769
770 if (!m->pParent->i_canChangeSettings())
771 return setError(E_INVALIDARG, tr("Cannot change audio channels while recording is enabled"));
772
773 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
774
775 if (m->bd->Audio.cChannels != (uint8_t)aChannels)
776 {
777 m->bd.backup();
778 m->bd->Audio.cChannels = (uint8_t)aChannels;
779
780 alock.release();
781
782 m->pParent->i_onSettingsChanged();
783 }
784
785 return S_OK;
786}
787
788HRESULT RecordingScreenSettings::getVideoCodec(RecordingVideoCodec_T *aCodec)
789{
790 AutoCaller autoCaller(this);
791 if (FAILED(autoCaller.rc())) return autoCaller.rc();
792
793 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
794
795 *aCodec = m->bd->Video.enmCodec;
796
797 return S_OK;
798}
799
800HRESULT RecordingScreenSettings::setVideoCodec(RecordingVideoCodec_T aCodec)
801{
802 AutoCaller autoCaller(this);
803 if (FAILED(autoCaller.rc())) return autoCaller.rc();
804
805 if (!m->pParent->i_canChangeSettings())
806 return setError(E_INVALIDARG, tr("Cannot change video codec while recording is enabled"));
807
808 if (aCodec != RecordingVideoCodec_VP8)
809 return setError(E_INVALIDARG, tr("Video codec not supported"));
810
811 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
812
813 if (m->bd->Video.enmCodec != aCodec)
814 {
815 m->bd.backup();
816 m->bd->Video.enmCodec = aCodec;
817
818 alock.release();
819
820 m->pParent->i_onSettingsChanged();
821 }
822
823 return S_OK;
824}
825
826HRESULT RecordingScreenSettings::getVideoDeadline(RecordingCodecDeadline_T *aDeadline)
827{
828 AutoCaller autoCaller(this);
829 if (FAILED(autoCaller.rc())) return autoCaller.rc();
830
831 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
832
833 *aDeadline = m->bd->Video.enmDeadline;
834
835 return S_OK;
836}
837
838HRESULT RecordingScreenSettings::setVideoDeadline(RecordingCodecDeadline_T aDeadline)
839{
840 AutoCaller autoCaller(this);
841 if (FAILED(autoCaller.rc())) return autoCaller.rc();
842
843 if (!m->pParent->i_canChangeSettings())
844 return setError(E_INVALIDARG, tr("Cannot change video deadline while recording is enabled"));
845
846 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
847
848 if (m->bd->Video.enmDeadline != aDeadline)
849 {
850 m->bd.backup();
851 m->bd->Video.enmDeadline = aDeadline;
852
853 alock.release();
854
855 m->pParent->i_onSettingsChanged();
856 }
857
858 return S_OK;
859}
860
861HRESULT RecordingScreenSettings::getVideoWidth(ULONG *aVideoWidth)
862{
863 AutoCaller autoCaller(this);
864 if (FAILED(autoCaller.rc())) return autoCaller.rc();
865
866 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
867
868 *aVideoWidth = m->bd->Video.ulWidth;
869
870 return S_OK;
871}
872
873HRESULT RecordingScreenSettings::setVideoWidth(ULONG aVideoWidth)
874{
875 AutoCaller autoCaller(this);
876 if (FAILED(autoCaller.rc())) return autoCaller.rc();
877
878 if (!m->pParent->i_canChangeSettings())
879 return setError(E_INVALIDARG, tr("Cannot change video width while recording is enabled"));
880
881 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
882
883 if (m->bd->Video.ulWidth != aVideoWidth)
884 {
885 m->bd.backup();
886 m->bd->Video.ulWidth = aVideoWidth;
887
888 alock.release();
889
890 m->pParent->i_onSettingsChanged();
891 }
892
893 return S_OK;
894}
895
896HRESULT RecordingScreenSettings::getVideoHeight(ULONG *aVideoHeight)
897{
898 AutoCaller autoCaller(this);
899 if (FAILED(autoCaller.rc())) return autoCaller.rc();
900
901 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
902
903 *aVideoHeight = m->bd->Video.ulHeight;
904
905 return S_OK;
906}
907
908HRESULT RecordingScreenSettings::setVideoHeight(ULONG aVideoHeight)
909{
910 AutoCaller autoCaller(this);
911 if (FAILED(autoCaller.rc())) return autoCaller.rc();
912
913 if (!m->pParent->i_canChangeSettings())
914 return setError(E_INVALIDARG, tr("Cannot change video height while recording is enabled"));
915
916 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
917
918 if (m->bd->Video.ulHeight != aVideoHeight)
919 {
920 m->bd.backup();
921 m->bd->Video.ulHeight = aVideoHeight;
922
923 alock.release();
924
925 m->pParent->i_onSettingsChanged();
926 }
927
928 return S_OK;
929}
930
931HRESULT RecordingScreenSettings::getVideoRate(ULONG *aVideoRate)
932{
933 AutoCaller autoCaller(this);
934 if (FAILED(autoCaller.rc())) return autoCaller.rc();
935
936 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
937
938 *aVideoRate = m->bd->Video.ulRate;
939
940 return S_OK;
941}
942
943HRESULT RecordingScreenSettings::setVideoRate(ULONG aVideoRate)
944{
945 AutoCaller autoCaller(this);
946 if (FAILED(autoCaller.rc())) return autoCaller.rc();
947
948 if (!m->pParent->i_canChangeSettings())
949 return setError(E_INVALIDARG, tr("Cannot change video rate while recording is enabled"));
950
951 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
952
953 if (m->bd->Video.ulRate != aVideoRate)
954 {
955 m->bd.backup();
956 m->bd->Video.ulRate = aVideoRate;
957
958 alock.release();
959
960 m->pParent->i_onSettingsChanged();
961 }
962
963 return S_OK;
964}
965
966HRESULT RecordingScreenSettings::getVideoRateControlMode(RecordingRateControlMode_T *aMode)
967{
968 AutoCaller autoCaller(this);
969 if (FAILED(autoCaller.rc())) return autoCaller.rc();
970
971 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
972
973 *aMode = RecordingRateControlMode_VBR; /** @todo Implement CBR. */
974
975 return S_OK;
976}
977
978HRESULT RecordingScreenSettings::setVideoRateControlMode(RecordingRateControlMode_T aMode)
979{
980 AutoCaller autoCaller(this);
981 if (FAILED(autoCaller.rc())) return autoCaller.rc();
982
983 if (!m->pParent->i_canChangeSettings())
984 return setError(E_INVALIDARG, tr("Cannot change video rate control mode while recording is enabled"));
985
986 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
987
988 /** @todo Implement this. */
989 RT_NOREF(aMode);
990
991 return E_NOTIMPL;
992}
993
994HRESULT RecordingScreenSettings::getVideoFPS(ULONG *aVideoFPS)
995{
996 AutoCaller autoCaller(this);
997 if (FAILED(autoCaller.rc())) return autoCaller.rc();
998
999 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1000
1001 *aVideoFPS = m->bd->Video.ulFPS;
1002
1003 return S_OK;
1004}
1005
1006HRESULT RecordingScreenSettings::setVideoFPS(ULONG aVideoFPS)
1007{
1008 AutoCaller autoCaller(this);
1009 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1010
1011 if (!m->pParent->i_canChangeSettings())
1012 return setError(E_INVALIDARG, tr("Cannot change video FPS while recording is enabled"));
1013
1014 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1015
1016 if (m->bd->Video.ulFPS != aVideoFPS)
1017 {
1018 m->bd.backup();
1019 m->bd->Video.ulFPS = aVideoFPS;
1020
1021 alock.release();
1022
1023 m->pParent->i_onSettingsChanged();
1024 }
1025
1026 return S_OK;
1027}
1028
1029HRESULT RecordingScreenSettings::getVideoScalingMode(RecordingVideoScalingMode_T *aMode)
1030{
1031 AutoCaller autoCaller(this);
1032 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1033
1034 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1035
1036 *aMode = RecordingVideoScalingMode_None; /** @todo Implement this. */
1037
1038 return S_OK;
1039}
1040
1041HRESULT RecordingScreenSettings::setVideoScalingMode(RecordingVideoScalingMode_T aMode)
1042{
1043 AutoCaller autoCaller(this);
1044 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1045
1046 if (!m->pParent->i_canChangeSettings())
1047 return setError(E_INVALIDARG, tr("Cannot change video scaling mode while recording is enabled"));
1048
1049 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1050
1051 /** @todo Implement this. */
1052 RT_NOREF(aMode);
1053
1054 return E_NOTIMPL;
1055}
1056
1057/**
1058 * Initializes data, internal version.
1059 *
1060 * @returns VBox status code.
1061 */
1062int RecordingScreenSettings::i_initInternal(void)
1063{
1064 AssertPtrReturn(m, VERR_INVALID_POINTER);
1065
1066 i_reference();
1067
1068 switch (m->bd->enmDest)
1069 {
1070 case RecordingDestination_File:
1071 {
1072 /* Note: Leave the file name empty here, which means using the default setting.
1073 * Important when comparing with the default settings! */
1074 break;
1075 }
1076
1077 default:
1078 break;
1079 }
1080
1081 return VINF_SUCCESS;
1082}
1083
1084
1085// public methods only for internal purposes
1086////////////////////////////////////////////////////////////////////////////////
1087
1088/**
1089 * Loads settings from the given machine node.
1090 * May be called once right after this object creation.
1091 *
1092 * @returns HRESULT
1093 * @param data Configuration settings to load.
1094 */
1095HRESULT RecordingScreenSettings::i_loadSettings(const settings::RecordingScreenSettings &data)
1096{
1097 AutoCaller autoCaller(this);
1098 AssertComRCReturnRC(autoCaller.rc());
1099
1100 AutoReadLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
1101 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1102
1103 // simply copy
1104 m->bd.assignCopy(&data);
1105 return S_OK;
1106}
1107
1108/**
1109 * Saves settings to the given machine node.
1110 *
1111 * @returns HRESULT
1112 * @param data Configuration settings to save to.
1113 */
1114HRESULT RecordingScreenSettings::i_saveSettings(settings::RecordingScreenSettings &data)
1115{
1116 LogThisFunc(("%p: Screen %RU32\n", this, m ? m->uScreenId : UINT32_MAX));
1117
1118 /* sanity */
1119 AutoCaller autoCaller(this);
1120 AssertComRCReturnRC(autoCaller.rc());
1121
1122 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1123
1124 data = *m->bd.data();
1125
1126 return S_OK;
1127}
1128
1129void RecordingScreenSettings::i_rollback(void)
1130{
1131 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1132 m->bd.rollback();
1133}
1134
1135void RecordingScreenSettings::i_commit(void)
1136{
1137 /* sanity */
1138 AutoCaller autoCaller(this);
1139 AssertComRCReturnVoid(autoCaller.rc());
1140
1141 /* sanity too */
1142 AutoCaller peerCaller(m->pPeer);
1143 AssertComRCReturnVoid(peerCaller.rc());
1144
1145 /* lock both for writing since we modify both (mPeer is "master" so locked
1146 * first) */
1147 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
1148
1149 if (m->bd.isBackedUp())
1150 {
1151 m->bd.commit();
1152 if (m->pPeer)
1153 {
1154 /* attach new data to the peer and reshare it */
1155 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
1156 m->pPeer->m->bd.attach(m->bd);
1157 }
1158 }
1159}
1160
1161void RecordingScreenSettings::i_copyFrom(RecordingScreenSettings *aThat)
1162{
1163 AssertReturnVoid(aThat != NULL);
1164
1165 /* sanity */
1166 AutoCaller autoCaller(this);
1167 AssertComRCReturnVoid(autoCaller.rc());
1168
1169 /* sanity too */
1170 AutoCaller thatCaller(aThat);
1171 AssertComRCReturnVoid(thatCaller.rc());
1172
1173 /* peer is not modified, lock it for reading (aThat is "master" so locked
1174 * first) */
1175 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1176 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1177
1178 /* this will back up current data */
1179 m->bd.assignCopy(aThat->m->bd);
1180}
1181
1182/**
1183 * Applies default screen recording settings.
1184 *
1185 * @note Locks this object for writing.
1186 */
1187void RecordingScreenSettings::i_applyDefaults(void)
1188{
1189 /* sanity */
1190 AutoCaller autoCaller(this);
1191 AssertComRCReturnVoid(autoCaller.rc());
1192
1193 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1194
1195 m->bd->applyDefaults();
1196}
1197
1198settings::RecordingScreenSettings &RecordingScreenSettings::i_getData(void)
1199{
1200 /* sanity */
1201 AutoCaller autoCaller(this);
1202 AssertComRC(autoCaller.rc());
1203
1204 AssertPtr(m);
1205 return *m->bd.data();
1206}
1207
1208/**
1209 * Increments the reference count.
1210 *
1211 * @returns New reference count.
1212 *
1213 * @note Internal reference count, to track object sharing across different recording settings objects
1214 * which share the same screen recording data.
1215 */
1216int32_t RecordingScreenSettings::i_reference(void)
1217{
1218 int cNewRefs = ASMAtomicIncS32(&m->cRefs); RT_NOREF(cNewRefs);
1219 LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
1220 return cNewRefs;
1221}
1222
1223/**
1224 * Decrements the reference count.
1225 *
1226 * @returns New reference count.
1227 *
1228 * @note Internal reference count, to track object sharing across different recording settings objects
1229 * which share the same screen recording data.
1230 */
1231int32_t RecordingScreenSettings::i_release(void)
1232{
1233 int32_t cNewRefs = ASMAtomicDecS32(&m->cRefs); RT_NOREF(cNewRefs);
1234 LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
1235 AssertReturn(cNewRefs >= 0, 0);
1236 return cNewRefs;
1237}
1238
1239/**
1240 * Returns the current reference count.
1241 *
1242 * @returns Current reference count.
1243 *
1244 * @note Internal reference count, to track object sharing across different recording settings objects
1245 * which share the same screen recording data.
1246 */
1247int32_t RecordingScreenSettings::i_getReferences(void)
1248{
1249 return ASMAtomicReadS32(&m->cRefs);
1250}
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