VirtualBox

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

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

Recording: Implemented support for Vorbis codec (provided by libvorbis, not enabled by default yet). This also makes all the codec handling more abstract by using a simple codec wrapper, to keep other places free from codec-specific as much as possible. Initial implementation works and output files are being recognized by media players, but there still are some timing bugs to resolve, as well as optimizing the performance. bugref:10275

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 31.2 KB
 
1/* $Id: RecordingScreenSettingsImpl.cpp 96175 2022-08-12 14:01:17Z 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_Opus)
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}
1234
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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