VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 7 weeks ago

Copyright year updates by scm.

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

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