VirtualBox

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

最後變更 在這個檔案從96407是 96407,由 vboxsync 提交於 3 年 前

scm copyright and license note update

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 31.5 KB
 
1/* $Id: RecordingScreenSettingsImpl.cpp 96407 2022-08-22 17:43:14Z 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.alldomusa.eu.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 m->bd.backup();
461 m->bd->File.strName = aFilename;
462
463 alock.release();
464
465 m->pParent->i_onSettingsChanged();
466 }
467
468 return S_OK;
469}
470
471HRESULT RecordingScreenSettings::getMaxTime(ULONG *aMaxTimeS)
472{
473 AutoCaller autoCaller(this);
474 if (FAILED(autoCaller.rc())) return autoCaller.rc();
475
476 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
477
478 *aMaxTimeS = m->bd->ulMaxTimeS;
479
480 return S_OK;
481}
482
483HRESULT RecordingScreenSettings::setMaxTime(ULONG aMaxTimeS)
484{
485 AutoCaller autoCaller(this);
486 if (FAILED(autoCaller.rc())) return autoCaller.rc();
487
488 if (!m->pParent->i_canChangeSettings())
489 return setError(E_INVALIDARG, tr("Cannot change maximum time while recording is enabled"));
490
491 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
492
493 if (m->bd->ulMaxTimeS != aMaxTimeS)
494 {
495 m->bd.backup();
496 m->bd->ulMaxTimeS = aMaxTimeS;
497
498 alock.release();
499
500 m->pParent->i_onSettingsChanged();
501 }
502
503 return S_OK;
504}
505
506HRESULT RecordingScreenSettings::getMaxFileSize(ULONG *aMaxFileSizeMB)
507{
508 AutoCaller autoCaller(this);
509 if (FAILED(autoCaller.rc())) return autoCaller.rc();
510
511 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
512
513 *aMaxFileSizeMB = m->bd->File.ulMaxSizeMB;
514
515 return S_OK;
516}
517
518HRESULT RecordingScreenSettings::setMaxFileSize(ULONG aMaxFileSize)
519{
520 AutoCaller autoCaller(this);
521 if (FAILED(autoCaller.rc())) return autoCaller.rc();
522
523 if (!m->pParent->i_canChangeSettings())
524 return setError(E_INVALIDARG, tr("Cannot change maximum file size while recording is enabled"));
525
526 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
527
528 if (m->bd->File.ulMaxSizeMB != aMaxFileSize)
529 {
530 m->bd.backup();
531 m->bd->File.ulMaxSizeMB = aMaxFileSize;
532
533 alock.release();
534
535 m->pParent->i_onSettingsChanged();
536 }
537
538 return S_OK;
539}
540
541HRESULT RecordingScreenSettings::getOptions(com::Utf8Str &aOptions)
542{
543 AutoCaller autoCaller(this);
544 if (FAILED(autoCaller.rc())) return autoCaller.rc();
545
546 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
547
548 aOptions = m->bd->strOptions;
549
550 return S_OK;
551}
552
553HRESULT RecordingScreenSettings::setOptions(const com::Utf8Str &aOptions)
554{
555 AutoCaller autoCaller(this);
556 if (FAILED(autoCaller.rc())) return autoCaller.rc();
557
558 if (!m->pParent->i_canChangeSettings())
559 return setError(E_INVALIDARG, tr("Cannot change options while recording is enabled"));
560
561 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
562
563 /* Note: Parsing and validation is done at codec level. */
564
565 m->bd.backup();
566 m->bd->strOptions = aOptions;
567
568 alock.release();
569
570 m->pParent->i_onSettingsChanged();
571
572 return S_OK;
573}
574
575HRESULT RecordingScreenSettings::getAudioCodec(RecordingAudioCodec_T *aCodec)
576{
577 AutoCaller autoCaller(this);
578 if (FAILED(autoCaller.rc())) return autoCaller.rc();
579
580 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
581
582 *aCodec = m->bd->Audio.enmCodec;
583
584 return S_OK;
585}
586
587HRESULT RecordingScreenSettings::setAudioCodec(RecordingAudioCodec_T aCodec)
588{
589 AutoCaller autoCaller(this);
590 if (FAILED(autoCaller.rc())) return autoCaller.rc();
591
592 if (!m->pParent->i_canChangeSettings())
593 return setError(E_INVALIDARG, tr("Cannot change audio codec while recording is enabled"));
594
595 if (aCodec != RecordingAudioCodec_OggVorbis)
596 return setError(E_INVALIDARG, tr("Audio codec not supported"));
597
598 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
599
600 if (m->bd->Audio.enmCodec != aCodec)
601 {
602 m->bd.backup();
603 m->bd->Audio.enmCodec = aCodec;
604
605 alock.release();
606
607 m->pParent->i_onSettingsChanged();
608 }
609
610 return S_OK;
611}
612
613HRESULT RecordingScreenSettings::getAudioDeadline(RecordingCodecDeadline_T *aDeadline)
614{
615 AutoCaller autoCaller(this);
616 if (FAILED(autoCaller.rc())) return autoCaller.rc();
617
618 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
619
620 *aDeadline = m->bd->Audio.enmDeadline;
621
622 return S_OK;
623}
624
625HRESULT RecordingScreenSettings::setAudioDeadline(RecordingCodecDeadline_T aDeadline)
626{
627 AutoCaller autoCaller(this);
628 if (FAILED(autoCaller.rc())) return autoCaller.rc();
629
630 if (!m->pParent->i_canChangeSettings())
631 return setError(E_INVALIDARG, tr("Cannot change audio deadline while recording is enabled"));
632
633 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
634
635 if (m->bd->Audio.enmDeadline != aDeadline)
636 {
637 m->bd.backup();
638 m->bd->Audio.enmDeadline = aDeadline;
639
640 alock.release();
641
642 m->pParent->i_onSettingsChanged();
643 }
644
645 return S_OK;
646}
647
648HRESULT RecordingScreenSettings::getAudioRateControlMode(RecordingRateControlMode_T *aMode)
649{
650 AutoCaller autoCaller(this);
651 if (FAILED(autoCaller.rc())) return autoCaller.rc();
652
653 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
654
655 *aMode = RecordingRateControlMode_VBR; /** @todo Implement CBR. */
656
657 return S_OK;
658}
659
660HRESULT RecordingScreenSettings::setAudioRateControlMode(RecordingRateControlMode_T aMode)
661{
662 AutoCaller autoCaller(this);
663 if (FAILED(autoCaller.rc())) return autoCaller.rc();
664
665 if (!m->pParent->i_canChangeSettings())
666 return setError(E_INVALIDARG, tr("Cannot change audio rate control mode while recording is enabled"));
667
668 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
669
670 /** @todo Implement this. */
671 RT_NOREF(aMode);
672
673 return E_NOTIMPL;
674}
675
676HRESULT RecordingScreenSettings::getAudioHz(ULONG *aHz)
677{
678 AutoCaller autoCaller(this);
679 if (FAILED(autoCaller.rc())) return autoCaller.rc();
680
681 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
682
683 *aHz = m->bd->Audio.uHz;
684
685 return S_OK;
686}
687
688HRESULT RecordingScreenSettings::setAudioHz(ULONG aHz)
689{
690 AutoCaller autoCaller(this);
691 if (FAILED(autoCaller.rc())) return autoCaller.rc();
692
693 if (!m->pParent->i_canChangeSettings())
694 return setError(E_INVALIDARG, tr("Cannot change audio Hertz rate while recording is enabled"));
695
696 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
697
698 if (m->bd->Audio.uHz != (uint16_t)aHz)
699 {
700 m->bd.backup();
701 m->bd->Audio.uHz = (uint16_t)aHz;
702
703 alock.release();
704
705 m->pParent->i_onSettingsChanged();
706 }
707
708 return S_OK;
709}
710
711HRESULT RecordingScreenSettings::getAudioBits(ULONG *aBits)
712{
713 AutoCaller autoCaller(this);
714 if (FAILED(autoCaller.rc())) return autoCaller.rc();
715
716 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
717
718 *aBits = m->bd->Audio.cBits;
719
720 return S_OK;
721}
722
723HRESULT RecordingScreenSettings::setAudioBits(ULONG aBits)
724{
725 AutoCaller autoCaller(this);
726 if (FAILED(autoCaller.rc())) return autoCaller.rc();
727
728 if (!m->pParent->i_canChangeSettings())
729 return setError(E_INVALIDARG, tr("Cannot change audio bits while recording is enabled"));
730
731 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
732
733 if (m->bd->Audio.cBits != (uint8_t)aBits)
734 {
735 m->bd.backup();
736 m->bd->Audio.cBits = (uint8_t)aBits;
737
738 alock.release();
739
740 m->pParent->i_onSettingsChanged();
741 }
742
743 return S_OK;
744}
745
746HRESULT RecordingScreenSettings::getAudioChannels(ULONG *aChannels)
747{
748 AutoCaller autoCaller(this);
749 if (FAILED(autoCaller.rc())) return autoCaller.rc();
750
751 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
752
753 *aChannels = m->bd->Audio.cChannels;
754
755 return S_OK;
756}
757
758HRESULT RecordingScreenSettings::setAudioChannels(ULONG aChannels)
759{
760 AutoCaller autoCaller(this);
761 if (FAILED(autoCaller.rc())) return autoCaller.rc();
762
763 if (!m->pParent->i_canChangeSettings())
764 return setError(E_INVALIDARG, tr("Cannot change audio channels while recording is enabled"));
765
766 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
767
768 if (m->bd->Audio.cChannels != (uint8_t)aChannels)
769 {
770 m->bd.backup();
771 m->bd->Audio.cChannels = (uint8_t)aChannels;
772
773 alock.release();
774
775 m->pParent->i_onSettingsChanged();
776 }
777
778 return S_OK;
779}
780
781HRESULT RecordingScreenSettings::getVideoCodec(RecordingVideoCodec_T *aCodec)
782{
783 AutoCaller autoCaller(this);
784 if (FAILED(autoCaller.rc())) return autoCaller.rc();
785
786 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
787
788 *aCodec = m->bd->Video.enmCodec;
789
790 return S_OK;
791}
792
793HRESULT RecordingScreenSettings::setVideoCodec(RecordingVideoCodec_T aCodec)
794{
795 AutoCaller autoCaller(this);
796 if (FAILED(autoCaller.rc())) return autoCaller.rc();
797
798 if (!m->pParent->i_canChangeSettings())
799 return setError(E_INVALIDARG, tr("Cannot change video codec while recording is enabled"));
800
801 if (aCodec != RecordingVideoCodec_VP8)
802 return setError(E_INVALIDARG, tr("Video codec not supported"));
803
804 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
805
806 if (m->bd->Video.enmCodec != aCodec)
807 {
808 m->bd.backup();
809 m->bd->Video.enmCodec = aCodec;
810
811 alock.release();
812
813 m->pParent->i_onSettingsChanged();
814 }
815
816 return S_OK;
817}
818
819HRESULT RecordingScreenSettings::getVideoDeadline(RecordingCodecDeadline_T *aDeadline)
820{
821 AutoCaller autoCaller(this);
822 if (FAILED(autoCaller.rc())) return autoCaller.rc();
823
824 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
825
826 *aDeadline = m->bd->Video.enmDeadline;
827
828 return S_OK;
829}
830
831HRESULT RecordingScreenSettings::setVideoDeadline(RecordingCodecDeadline_T aDeadline)
832{
833 AutoCaller autoCaller(this);
834 if (FAILED(autoCaller.rc())) return autoCaller.rc();
835
836 if (!m->pParent->i_canChangeSettings())
837 return setError(E_INVALIDARG, tr("Cannot change video deadline while recording is enabled"));
838
839 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
840
841 if (m->bd->Video.enmDeadline != aDeadline)
842 {
843 m->bd.backup();
844 m->bd->Video.enmDeadline = aDeadline;
845
846 alock.release();
847
848 m->pParent->i_onSettingsChanged();
849 }
850
851 return S_OK;
852}
853
854HRESULT RecordingScreenSettings::getVideoWidth(ULONG *aVideoWidth)
855{
856 AutoCaller autoCaller(this);
857 if (FAILED(autoCaller.rc())) return autoCaller.rc();
858
859 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
860
861 *aVideoWidth = m->bd->Video.ulWidth;
862
863 return S_OK;
864}
865
866HRESULT RecordingScreenSettings::setVideoWidth(ULONG aVideoWidth)
867{
868 AutoCaller autoCaller(this);
869 if (FAILED(autoCaller.rc())) return autoCaller.rc();
870
871 if (!m->pParent->i_canChangeSettings())
872 return setError(E_INVALIDARG, tr("Cannot change video width while recording is enabled"));
873
874 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
875
876 if (m->bd->Video.ulWidth != aVideoWidth)
877 {
878 m->bd.backup();
879 m->bd->Video.ulWidth = aVideoWidth;
880
881 alock.release();
882
883 m->pParent->i_onSettingsChanged();
884 }
885
886 return S_OK;
887}
888
889HRESULT RecordingScreenSettings::getVideoHeight(ULONG *aVideoHeight)
890{
891 AutoCaller autoCaller(this);
892 if (FAILED(autoCaller.rc())) return autoCaller.rc();
893
894 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
895
896 *aVideoHeight = m->bd->Video.ulHeight;
897
898 return S_OK;
899}
900
901HRESULT RecordingScreenSettings::setVideoHeight(ULONG aVideoHeight)
902{
903 AutoCaller autoCaller(this);
904 if (FAILED(autoCaller.rc())) return autoCaller.rc();
905
906 if (!m->pParent->i_canChangeSettings())
907 return setError(E_INVALIDARG, tr("Cannot change video height while recording is enabled"));
908
909 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
910
911 if (m->bd->Video.ulHeight != aVideoHeight)
912 {
913 m->bd.backup();
914 m->bd->Video.ulHeight = aVideoHeight;
915
916 alock.release();
917
918 m->pParent->i_onSettingsChanged();
919 }
920
921 return S_OK;
922}
923
924HRESULT RecordingScreenSettings::getVideoRate(ULONG *aVideoRate)
925{
926 AutoCaller autoCaller(this);
927 if (FAILED(autoCaller.rc())) return autoCaller.rc();
928
929 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
930
931 *aVideoRate = m->bd->Video.ulRate;
932
933 return S_OK;
934}
935
936HRESULT RecordingScreenSettings::setVideoRate(ULONG aVideoRate)
937{
938 AutoCaller autoCaller(this);
939 if (FAILED(autoCaller.rc())) return autoCaller.rc();
940
941 if (!m->pParent->i_canChangeSettings())
942 return setError(E_INVALIDARG, tr("Cannot change video rate while recording is enabled"));
943
944 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
945
946 if (m->bd->Video.ulRate != aVideoRate)
947 {
948 m->bd.backup();
949 m->bd->Video.ulRate = aVideoRate;
950
951 alock.release();
952
953 m->pParent->i_onSettingsChanged();
954 }
955
956 return S_OK;
957}
958
959HRESULT RecordingScreenSettings::getVideoRateControlMode(RecordingRateControlMode_T *aMode)
960{
961 AutoCaller autoCaller(this);
962 if (FAILED(autoCaller.rc())) return autoCaller.rc();
963
964 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
965
966 *aMode = RecordingRateControlMode_VBR; /** @todo Implement CBR. */
967
968 return S_OK;
969}
970
971HRESULT RecordingScreenSettings::setVideoRateControlMode(RecordingRateControlMode_T aMode)
972{
973 AutoCaller autoCaller(this);
974 if (FAILED(autoCaller.rc())) return autoCaller.rc();
975
976 if (!m->pParent->i_canChangeSettings())
977 return setError(E_INVALIDARG, tr("Cannot change video rate control mode while recording is enabled"));
978
979 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
980
981 /** @todo Implement this. */
982 RT_NOREF(aMode);
983
984 return E_NOTIMPL;
985}
986
987HRESULT RecordingScreenSettings::getVideoFPS(ULONG *aVideoFPS)
988{
989 AutoCaller autoCaller(this);
990 if (FAILED(autoCaller.rc())) return autoCaller.rc();
991
992 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
993
994 *aVideoFPS = m->bd->Video.ulFPS;
995
996 return S_OK;
997}
998
999HRESULT RecordingScreenSettings::setVideoFPS(ULONG aVideoFPS)
1000{
1001 AutoCaller autoCaller(this);
1002 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1003
1004 if (!m->pParent->i_canChangeSettings())
1005 return setError(E_INVALIDARG, tr("Cannot change video FPS while recording is enabled"));
1006
1007 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1008
1009 if (m->bd->Video.ulFPS != aVideoFPS)
1010 {
1011 m->bd.backup();
1012 m->bd->Video.ulFPS = aVideoFPS;
1013
1014 alock.release();
1015
1016 m->pParent->i_onSettingsChanged();
1017 }
1018
1019 return S_OK;
1020}
1021
1022HRESULT RecordingScreenSettings::getVideoScalingMode(RecordingVideoScalingMode_T *aMode)
1023{
1024 AutoCaller autoCaller(this);
1025 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1026
1027 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1028
1029 *aMode = RecordingVideoScalingMode_None; /** @todo Implement this. */
1030
1031 return S_OK;
1032}
1033
1034HRESULT RecordingScreenSettings::setVideoScalingMode(RecordingVideoScalingMode_T aMode)
1035{
1036 AutoCaller autoCaller(this);
1037 if (FAILED(autoCaller.rc())) return autoCaller.rc();
1038
1039 if (!m->pParent->i_canChangeSettings())
1040 return setError(E_INVALIDARG, tr("Cannot change video scaling mode while recording is enabled"));
1041
1042 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1043
1044 /** @todo Implement this. */
1045 RT_NOREF(aMode);
1046
1047 return E_NOTIMPL;
1048}
1049
1050/**
1051 * Initializes data, internal version.
1052 *
1053 * @returns VBox status code.
1054 */
1055int RecordingScreenSettings::i_initInternal(void)
1056{
1057 AssertPtrReturn(m, VERR_INVALID_POINTER);
1058
1059 i_reference();
1060
1061 switch (m->bd->enmDest)
1062 {
1063 case RecordingDestination_File:
1064 {
1065 /* Note: Leave the file name empty here, which means using the default setting.
1066 * Important when comparing with the default settings! */
1067 break;
1068 }
1069
1070 default:
1071 break;
1072 }
1073
1074 return VINF_SUCCESS;
1075}
1076
1077
1078// public methods only for internal purposes
1079////////////////////////////////////////////////////////////////////////////////
1080
1081/**
1082 * Loads settings from the given machine node.
1083 * May be called once right after this object creation.
1084 *
1085 * @returns HRESULT
1086 * @param data Configuration settings to load.
1087 */
1088HRESULT RecordingScreenSettings::i_loadSettings(const settings::RecordingScreenSettings &data)
1089{
1090 AutoCaller autoCaller(this);
1091 AssertComRCReturnRC(autoCaller.rc());
1092
1093 AutoReadLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
1094 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1095
1096 // simply copy
1097 m->bd.assignCopy(&data);
1098 return S_OK;
1099}
1100
1101/**
1102 * Saves settings to the given machine node.
1103 *
1104 * @returns HRESULT
1105 * @param data Configuration settings to save to.
1106 */
1107HRESULT RecordingScreenSettings::i_saveSettings(settings::RecordingScreenSettings &data)
1108{
1109 LogThisFunc(("%p: Screen %RU32\n", this, m ? m->uScreenId : UINT32_MAX));
1110
1111 /* sanity */
1112 AutoCaller autoCaller(this);
1113 AssertComRCReturnRC(autoCaller.rc());
1114
1115 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1116
1117 data = *m->bd.data();
1118
1119 return S_OK;
1120}
1121
1122void RecordingScreenSettings::i_rollback(void)
1123{
1124 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1125 m->bd.rollback();
1126}
1127
1128void RecordingScreenSettings::i_commit(void)
1129{
1130 /* sanity */
1131 AutoCaller autoCaller(this);
1132 AssertComRCReturnVoid(autoCaller.rc());
1133
1134 /* sanity too */
1135 AutoCaller peerCaller(m->pPeer);
1136 AssertComRCReturnVoid(peerCaller.rc());
1137
1138 /* lock both for writing since we modify both (mPeer is "master" so locked
1139 * first) */
1140 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
1141
1142 if (m->bd.isBackedUp())
1143 {
1144 m->bd.commit();
1145 if (m->pPeer)
1146 {
1147 /* attach new data to the peer and reshare it */
1148 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
1149 m->pPeer->m->bd.attach(m->bd);
1150 }
1151 }
1152}
1153
1154void RecordingScreenSettings::i_copyFrom(RecordingScreenSettings *aThat)
1155{
1156 AssertReturnVoid(aThat != NULL);
1157
1158 /* sanity */
1159 AutoCaller autoCaller(this);
1160 AssertComRCReturnVoid(autoCaller.rc());
1161
1162 /* sanity too */
1163 AutoCaller thatCaller(aThat);
1164 AssertComRCReturnVoid(thatCaller.rc());
1165
1166 /* peer is not modified, lock it for reading (aThat is "master" so locked
1167 * first) */
1168 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
1169 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
1170
1171 /* this will back up current data */
1172 m->bd.assignCopy(aThat->m->bd);
1173}
1174
1175/**
1176 * Applies default screen recording settings.
1177 *
1178 * @note Locks this object for writing.
1179 */
1180void RecordingScreenSettings::i_applyDefaults(void)
1181{
1182 /* sanity */
1183 AutoCaller autoCaller(this);
1184 AssertComRCReturnVoid(autoCaller.rc());
1185
1186 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1187
1188 m->bd->applyDefaults();
1189}
1190
1191settings::RecordingScreenSettings &RecordingScreenSettings::i_getData(void)
1192{
1193 /* sanity */
1194 AutoCaller autoCaller(this);
1195 AssertComRC(autoCaller.rc());
1196
1197 AssertPtr(m);
1198 return *m->bd.data();
1199}
1200
1201/**
1202 * Increments the reference count.
1203 *
1204 * @returns New reference count.
1205 *
1206 * @note Internal reference count, to track object sharing across different recording settings objects
1207 * which share the same screen recording data.
1208 */
1209int32_t RecordingScreenSettings::i_reference(void)
1210{
1211 int cNewRefs = ASMAtomicIncS32(&m->cRefs); RT_NOREF(cNewRefs);
1212 LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
1213 return cNewRefs;
1214}
1215
1216/**
1217 * Decrements the reference count.
1218 *
1219 * @returns New reference count.
1220 *
1221 * @note Internal reference count, to track object sharing across different recording settings objects
1222 * which share the same screen recording data.
1223 */
1224int32_t RecordingScreenSettings::i_release(void)
1225{
1226 int32_t cNewRefs = ASMAtomicDecS32(&m->cRefs); RT_NOREF(cNewRefs);
1227 LogThisFunc(("%p: cRefs -> %RI32\n", this, cNewRefs));
1228 AssertReturn(cNewRefs >= 0, 0);
1229 return cNewRefs;
1230}
1231
1232/**
1233 * Returns the current reference count.
1234 *
1235 * @returns Current reference count.
1236 *
1237 * @note Internal reference count, to track object sharing across different recording settings objects
1238 * which share the same screen recording data.
1239 */
1240int32_t RecordingScreenSettings::i_getReferences(void)
1241{
1242 return ASMAtomicReadS32(&m->cRefs);
1243}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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