VirtualBox

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

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

Recording: Removed support for Opus. bugref:10275

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

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