VirtualBox

Changeset 95639 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jul 14, 2022 8:30:45 AM (3 years ago)
Author:
vboxsync
Message:

Recording: Settings handling fixes / overhaul. This adds the ability to handle per-screen settings, which can be different from the first screen (screen 0). Also fixed a couple of bugs regarding snapshot handling and persistence (committing, rolling back, ++) in that area. FE/VBoxManage now can also list the per-screen settings. Added some further @todos. bugref:9286

Location:
trunk/src/VBox/Main
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r95423 r95639  
    168168    void i_recordingDestroy(void);
    169169    int i_recordingEnable(BOOL fEnable, util::AutoWriteLock *pAutoLock);
    170     int i_recordingGetSettings(settings::RecordingSettings &Settings);
     170    int i_recordingGetSettings(settings::RecordingSettings &recording);
    171171    int i_recordingStart(util::AutoWriteLock *pAutoLock = NULL);
    172172    int i_recordingStop(util::AutoWriteLock *pAutoLock = NULL);
  • trunk/src/VBox/Main/include/MachineImpl.h

    r95450 r95639  
    679679                           const settings::Hardware &data,
    680680                           const settings::Debugging *pDbg,
    681                            const settings::Autostart *pAutostart);
     681                           const settings::Autostart *pAutostart,
     682                           const settings::RecordingSettings &recording);
    682683    HRESULT i_loadDebugging(const settings::Debugging *pDbg);
    683684    HRESULT i_loadAutostart(const settings::Autostart *pAutostart);
     
    718719    HRESULT i_saveAllSnapshots(settings::MachineConfigFile &config);
    719720    HRESULT i_saveHardware(settings::Hardware &data, settings::Debugging *pDbg,
    720                            settings::Autostart *pAutostart);
     721                           settings::Autostart *pAutostart, settings::RecordingSettings &recording);
    721722    HRESULT i_saveStorageControllers(settings::Storage &data);
    722723    HRESULT i_saveStorageDevices(ComObjPtr<StorageController> aStorageController,
     
    16271628                             const settings::Debugging *pDbg,
    16281629                             const settings::Autostart *pAutostart,
     1630                             const settings::RecordingSettings &recording,
    16291631                             IN_GUID aSnapshotId,
    16301632                             const Utf8Str &aStateFilePath);
  • trunk/src/VBox/Main/include/RecordingScreenSettingsImpl.h

    r93115 r95639  
    4747    HRESULT init(RecordingSettings *aParent, RecordingScreenSettings *aThat);
    4848    HRESULT initCopy(RecordingSettings *aParent, RecordingScreenSettings *aThat);
    49     void uninit();
     49    void uninit(void);
     50
     51    // public methods only for internal purposes
     52    HRESULT i_loadSettings(const settings::RecordingScreenSettings &data);
     53    HRESULT i_saveSettings(settings::RecordingScreenSettings &data);
     54
     55    void i_rollback(void);
     56    void i_commit(void);
     57    void i_copyFrom(RecordingScreenSettings *aThat);
     58    void i_applyDefaults(void);
     59
     60    settings::RecordingScreenSettings &i_getData(void);
    5061
    5162private:
  • trunk/src/VBox/Main/include/RecordingSettingsImpl.h

    r93115 r95639  
    5252    HRESULT i_saveSettings(settings::RecordingSettings &data);
    5353
    54     void i_rollback();
    55     void i_commit();
    56     void i_copyFrom(RecordingSettings *aThat);
    57     void i_applyDefaults(void);
     54    void    i_rollback(void);
     55    void    i_commit(void);
     56    HRESULT i_copyFrom(RecordingSettings *aThat);
     57    void    i_applyDefaults(void);
    5858
    59     int i_getDefaultFilename(Utf8Str &strFile, bool fWithFileExtension);
     59    int i_getDefaultFilename(Utf8Str &strFile, uint32_t idScreen, bool fWithFileExtension);
    6060    bool i_canChangeSettings(void);
    6161    void i_onSettingsChanged(void);
     
    6464
    6565    /** Map of screen settings objects. The key specifies the screen ID. */
    66     typedef std::map <uint32_t, ComObjPtr<RecordingScreenSettings> > RecordScreenSettingsMap;
     66    typedef std::map <uint32_t, ComObjPtr<RecordingScreenSettings> > RecordingScreenSettingsObjMap;
    6767
    6868    void i_reset(void);
    69     int i_syncToMachineDisplays(uint32_t cMonitors);
    70     int i_createScreenObj(RecordScreenSettingsMap &screenSettingsMap, uint32_t uScreenId, const settings::RecordingScreenSettings &data);
    71     int i_destroyScreenObj(RecordScreenSettingsMap &screenSettingsMap, uint32_t uScreenId);
    72     int i_destroyAllScreenObj(RecordScreenSettingsMap &screenSettingsMap);
     69    int i_syncToMachineDisplays(uint32_t cDisplays);
     70    int i_createScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen, const settings::RecordingScreenSettings &data);
     71    int i_destroyScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen);
     72    int i_destroyAllScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap);
    7373
    7474private:
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r95423 r95639  
    72487248#ifdef VBOX_WITH_RECORDING
    72497249
    7250 int Console::i_recordingGetSettings(settings::RecordingSettings &Settings)
     7250int Console::i_recordingGetSettings(settings::RecordingSettings &recording)
    72517251{
    72527252    Assert(mMachine.isNotNull());
    72537253
    7254     Settings.applyDefaults();
     7254    recording.applyDefaults();
    72557255
    72567256    ComPtr<IRecordingSettings> pRecordSettings;
     
    72617261    hrc = pRecordSettings->COMGETTER(Enabled)(&fTemp);
    72627262    AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7263     Settings.fEnabled = RT_BOOL(fTemp);
    7264 
    7265     SafeIfaceArray<IRecordingScreenSettings> paRecordingScreens;
    7266     hrc = pRecordSettings->COMGETTER(Screens)(ComSafeArrayAsOutParam(paRecordingScreens));
     7263    recording.common.fEnabled = RT_BOOL(fTemp);
     7264
     7265    SafeIfaceArray<IRecordingScreenSettings> paRecScreens;
     7266    hrc = pRecordSettings->COMGETTER(Screens)(ComSafeArrayAsOutParam(paRecScreens));
    72677267    AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    72687268
    7269     for (unsigned long i = 0; i < (unsigned long)paRecordingScreens.size(); ++i)
    7270     {
    7271         settings::RecordingScreenSettings RecordScreenSettings;
    7272         ComPtr<IRecordingScreenSettings> pRecordScreenSettings = paRecordingScreens[i];
    7273 
    7274         hrc = pRecordScreenSettings->COMGETTER(Enabled)(&fTemp);
     7269    for (unsigned long i = 0; i < (unsigned long)paRecScreens.size(); ++i)
     7270    {
     7271        settings::RecordingScreenSettings recScreenSettings;
     7272        ComPtr<IRecordingScreenSettings> pRecScreenSettings = paRecScreens[i];
     7273
     7274        hrc = pRecScreenSettings->COMGETTER(Enabled)(&fTemp);
    72757275        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7276         RecordScreenSettings.fEnabled = RT_BOOL(fTemp);
    7277         hrc = pRecordScreenSettings->COMGETTER(MaxTime)((ULONG *)&RecordScreenSettings.ulMaxTimeS);
     7276        recScreenSettings.fEnabled = RT_BOOL(fTemp);
     7277        hrc = pRecScreenSettings->COMGETTER(MaxTime)((ULONG *)&recScreenSettings.ulMaxTimeS);
    72787278        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7279         hrc = pRecordScreenSettings->COMGETTER(MaxFileSize)((ULONG *)&RecordScreenSettings.File.ulMaxSizeMB);
     7279        hrc = pRecScreenSettings->COMGETTER(MaxFileSize)((ULONG *)&recScreenSettings.File.ulMaxSizeMB);
    72807280        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    72817281        Bstr bstrTemp;
    7282         hrc = pRecordScreenSettings->COMGETTER(Filename)(bstrTemp.asOutParam());
     7282        hrc = pRecScreenSettings->COMGETTER(Filename)(bstrTemp.asOutParam());
    72837283        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7284         RecordScreenSettings.File.strName = bstrTemp;
    7285         hrc = pRecordScreenSettings->COMGETTER(Options)(bstrTemp.asOutParam());
     7284        recScreenSettings.File.strName = bstrTemp;
     7285        hrc = pRecScreenSettings->COMGETTER(Options)(bstrTemp.asOutParam());
    72867286        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7287         RecordScreenSettings.strOptions = bstrTemp;
    7288         hrc = pRecordScreenSettings->COMGETTER(VideoWidth)((ULONG *)&RecordScreenSettings.Video.ulWidth);
     7287        recScreenSettings.strOptions = bstrTemp;
     7288        hrc = pRecScreenSettings->COMGETTER(VideoWidth)((ULONG *)&recScreenSettings.Video.ulWidth);
    72897289        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7290         hrc = pRecordScreenSettings->COMGETTER(VideoHeight)((ULONG *)&RecordScreenSettings.Video.ulHeight);
     7290        hrc = pRecScreenSettings->COMGETTER(VideoHeight)((ULONG *)&recScreenSettings.Video.ulHeight);
    72917291        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7292         hrc = pRecordScreenSettings->COMGETTER(VideoRate)((ULONG *)&RecordScreenSettings.Video.ulRate);
     7292        hrc = pRecScreenSettings->COMGETTER(VideoRate)((ULONG *)&recScreenSettings.Video.ulRate);
    72937293        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    7294         hrc = pRecordScreenSettings->COMGETTER(VideoFPS)((ULONG *)&RecordScreenSettings.Video.ulFPS);
     7294        hrc = pRecScreenSettings->COMGETTER(VideoFPS)((ULONG *)&recScreenSettings.Video.ulFPS);
    72957295        AssertComRCReturn(hrc, VERR_INVALID_PARAMETER);
    72967296
    7297         Settings.mapScreens[i] = RecordScreenSettings;
    7298     }
    7299 
    7300     Assert(Settings.mapScreens.size() == paRecordingScreens.size());
     7297        recording.mapScreens[i] = recScreenSettings;
     7298    }
     7299
     7300    Assert(recording.mapScreens.size() == paRecScreens.size());
    73017301
    73027302    return VINF_SUCCESS;
  • trunk/src/VBox/Main/src-client/Recording.cpp

    r94950 r95639  
    151151        return vrc;
    152152
    153     settings::RecordingScreenMap::const_iterator itScreen = a_Settings.mapScreens.begin();
     153    settings::RecordingScreenSettingsMap::const_iterator itScreen = a_Settings.mapScreens.begin();
    154154    while (itScreen != a_Settings.mapScreens.end())
    155155    {
     
    206206
    207207    if (RT_SUCCESS(vrc)) /* Wait for the thread to start. */
    208         vrc = RTThreadUserWait(this->Thread, 30 * RT_MS_1SEC /* 30s timeout */);
     208        vrc = RTThreadUserWait(this->Thread, RT_MS_30SEC /* 30s timeout */);
    209209
    210210    if (RT_SUCCESS(vrc))
     
    237237    int vrc = threadNotify();
    238238    if (RT_SUCCESS(vrc))
    239         vrc = RTThreadWait(this->Thread, 30 * 1000 /* 10s timeout */, NULL);
     239        vrc = RTThreadWait(this->Thread, RT_MS_30SEC /* 30s timeout */, NULL);
    240240
    241241    lock();
     
    295295
    296296    if (RTCritSectIsInitialized(&this->CritSect))
    297     {
    298         Assert(RTCritSectGetWaiters(&this->CritSect) == -1);
    299297        RTCritSectDelete(&this->CritSect);
    300     }
    301298
    302299    this->enmState = RECORDINGSTS_UNINITIALIZED;
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r95556 r95639  
    510510        mTrustedPlatformModule->i_applyDefaults(aOsType);
    511511
    512         /* Apply record defaults. */
     512        /* Apply recording defaults. */
    513513        mRecordingSettings->i_applyDefaults();
    514514
     
    86328632    mBIOSSettings->init(this);
    86338633
     8634    /* create associated recording settings object */
     8635    unconst(mRecordingSettings).createObject();
     8636    mRecordingSettings->init(this);
     8637
    86348638    /* create associated trusted platform module object */
    86358639    unconst(mTrustedPlatformModule).createObject();
     
    86398643    unconst(mNvramStore).createObject();
    86408644    mNvramStore->init(this);
    8641 
    8642     /* create associated record settings object */
    8643     unconst(mRecordingSettings).createObject();
    8644     mRecordingSettings->init(this);
    86458645
    86468646    /* create the graphics adapter object (always present) */
     
    87718771    }
    87728772
     8773    if (mRecordingSettings)
     8774    {
     8775        mRecordingSettings->uninit();
     8776        unconst(mRecordingSettings).setNull();
     8777    }
     8778
    87738779    if (mTrustedPlatformModule)
    87748780    {
     
    87818787        mNvramStore->uninit();
    87828788        unconst(mNvramStore).setNull();
    8783     }
    8784 
    8785     if (mRecordingSettings)
    8786     {
    8787         mRecordingSettings->uninit();
    8788         unconst(mRecordingSettings).setNull();
    87898789    }
    87908790
     
    90829082
    90839083    // hardware data
    9084     rc = i_loadHardware(puuidRegistry, NULL, config.hardwareMachine, &config.debugging, &config.autostart);
     9084    rc = i_loadHardware(puuidRegistry, NULL, config.hardwareMachine, &config.debugging, &config.autostart,
     9085                        config.recordingSettings);
    90859086    if (FAILED(rc)) return rc;
    90869087
     
    91649165                                                &current->debugging,
    91659166                                                &current->autostart,
     9167                                                current->recordingSettings,
    91669168                                                current->uuid.ref(),
    91679169                                                strStateFile);
     
    92149216 * @param data          Reference to the hardware settings.
    92159217 * @param pDbg          Pointer to the debugging settings.
    9216  * @param pAutostart    Pointer to the autostart settings.
     9218 * @param pAutostart    Pointer to the autostart settings
     9219 * @param recording     Reference to recording settings.
    92179220 */
    92189221HRESULT Machine::i_loadHardware(const Guid *puuidRegistry,
     
    92209223                                const settings::Hardware &data,
    92219224                                const settings::Debugging *pDbg,
    9222                                 const settings::Autostart *pAutostart)
     9225                                const settings::Autostart *pAutostart,
     9226                                const settings::RecordingSettings &recording)
    92239227{
    92249228    AssertReturn(!i_isSessionMachine(), E_FAIL);
     
    93269330        if (FAILED(rc)) return rc;
    93279331
     9332        /* Recording */
     9333        rc = mRecordingSettings->i_loadSettings(recording);
     9334        if (FAILED(rc)) return rc;
     9335
    93289336        /* Trusted Platform Module */
    93299337        rc = mTrustedPlatformModule->i_loadSettings(data.tpmSettings);
     
    93319339
    93329340        rc = mNvramStore->i_loadSettings(data.nvramSettings);
    9333         if (FAILED(rc)) return rc;
    9334 
    9335         /* Recording settings */
    9336         rc = mRecordingSettings->i_loadSettings(data.recordingSettings);
    93379341        if (FAILED(rc)) return rc;
    93389342
     
    1057810582    /// @todo Live Migration:        config.fTeleported = (mData->mMachineState == MachineState_Teleported);
    1057910583
    10580     HRESULT rc = i_saveHardware(config.hardwareMachine, &config.debugging, &config.autostart);
    10581     if (FAILED(rc)) throw rc;
     10584    HRESULT hrc = i_saveHardware(config.hardwareMachine, &config.debugging, &config.autostart, config.recordingSettings);
     10585    if (FAILED(hrc)) throw hrc;
    1058210586
    1058310587    // save machine's media registry if this is VirtualBox 4.0 or later
     
    1059410598
    1059510599    // save snapshots
    10596     rc = i_saveAllSnapshots(config);
    10597     if (FAILED(rc)) throw rc;
     10600    hrc = i_saveAllSnapshots(config);
     10601    if (FAILED(hrc)) throw hrc;
    1059810602}
    1059910603
     
    1065110655 *  @param pAutostart     Pointer to the settings object for the autostart config
    1065210656 *                        which happens to live in mHWData.
     10657 *  @param recording      Reference to reecording settings.
    1065310658 */
    1065410659HRESULT Machine::i_saveHardware(settings::Hardware &data, settings::Debugging *pDbg,
    10655                                 settings::Autostart *pAutostart)
     10660                                settings::Autostart *pAutostart, settings::RecordingSettings &recording)
    1065610661{
    1065710662    HRESULT rc = S_OK;
     
    1075710762        if (FAILED(rc)) throw rc;
    1075810763
     10764        /* Recording settings. */
     10765        rc = mRecordingSettings->i_saveSettings(recording);
     10766        if (FAILED(rc)) throw rc;
     10767
    1075910768        /* Trusted Platform Module settings (required) */
    1076010769        rc = mTrustedPlatformModule->i_saveSettings(data.tpmSettings);
     
    1076310772        /* NVRAM settings (required) */
    1076410773        rc = mNvramStore->i_saveSettings(data.nvramSettings);
    10765         if (FAILED(rc)) throw rc;
    10766 
    10767         /* Recording settings (required) */
    10768         rc = mRecordingSettings->i_saveSettings(data.recordingSettings);
    1076910774        if (FAILED(rc)) throw rc;
    1077010775
     
    1232512330        mBIOSSettings->i_rollback();
    1232612331
     12332    if (mRecordingSettings && (mData->flModifications & IsModified_Recording))
     12333        mRecordingSettings->i_rollback();
     12334
    1232712335    if (mTrustedPlatformModule)
    1232812336        mTrustedPlatformModule->i_rollback();
     
    1233012338    if (mNvramStore)
    1233112339        mNvramStore->i_rollback();
    12332 
    12333     if (mRecordingSettings && (mData->flModifications & IsModified_Recording))
    12334         mRecordingSettings->i_rollback();
    1233512340
    1233612341    if (mGraphicsAdapter && (mData->flModifications & IsModified_GraphicsAdapter))
     
    1245612461
    1245712462    mBIOSSettings->i_commit();
     12463    mRecordingSettings->i_commit();
    1245812464    mTrustedPlatformModule->i_commit();
    1245912465    mNvramStore->i_commit();
    12460     mRecordingSettings->i_commit();
    1246112466    mGraphicsAdapter->i_commit();
    1246212467    mVRDEServer->i_commit();
     
    1271212717
    1271312718    mBIOSSettings->i_copyFrom(aThat->mBIOSSettings);
     12719    mRecordingSettings->i_copyFrom(aThat->mRecordingSettings);
    1271412720    mTrustedPlatformModule->i_copyFrom(aThat->mTrustedPlatformModule);
    1271512721    mNvramStore->i_copyFrom(aThat->mNvramStore);
    12716     mRecordingSettings->i_copyFrom(aThat->mRecordingSettings);
    1271712722    mGraphicsAdapter->i_copyFrom(aThat->mGraphicsAdapter);
    1271812723    mVRDEServer->i_copyFrom(aThat->mVRDEServer);
     
    1309013095    mBIOSSettings->init(this, aMachine->mBIOSSettings);
    1309113096
     13097    unconst(mRecordingSettings).createObject();
     13098    mRecordingSettings->init(this, aMachine->mRecordingSettings);
     13099
    1309213100    unconst(mTrustedPlatformModule).createObject();
    1309313101    mTrustedPlatformModule->init(this, aMachine->mTrustedPlatformModule);
     
    1309613104    mNvramStore->init(this, aMachine->mNvramStore);
    1309713105
    13098     unconst(mRecordingSettings).createObject();
    13099     mRecordingSettings->init(this, aMachine->mRecordingSettings);
    1310013106    /* create another GraphicsAdapter object that will be mutable */
    1310113107    unconst(mGraphicsAdapter).createObject();
  • trunk/src/VBox/Main/src-server/RecordingScreenSettingsImpl.cpp

    r93115 r95639  
    5353
    5454// constructor / destructor
    55 /////////////////////////////////////////////////////////////////////////////
     55////////////////////////////////////////////////////////////////////////////////
    5656
    5757DEFINE_EMPTY_CTOR_DTOR(RecordingScreenSettings)
     
    6969
    7070// public initializer/uninitializer for internal purposes only
    71 /////////////////////////////////////////////////////////////////////////////
     71////////////////////////////////////////////////////////////////////////////////
    7272
    7373/**
     
    7979                                      const settings::RecordingScreenSettings& aThat)
    8080{
    81     LogFlowThisFuncEnter();
    8281    LogFlowThisFunc(("aParent: %p\n", aParent));
    8382
     
    9998    m->bd->operator=(aThat);
    10099
    101     HRESULT rc = S_OK;
     100    HRESULT hrc = S_OK;
    102101
    103102    int vrc = i_initInternal();
     
    109108    {
    110109        autoInitSpan.setFailed();
    111         rc = E_UNEXPECTED;
     110        hrc = E_UNEXPECTED;
    112111    }
    113112
    114113    LogFlowThisFuncLeave();
    115     return rc;
     114    return hrc;
    116115}
    117116
     
    122121 *
    123122 *  @note This object must be destroyed before the original object
    124  *  it shares data with is destroyed.
     123 *        it shares data with is destroyed.
    125124 */
    126125HRESULT RecordingScreenSettings::init(RecordingSettings *aParent, RecordingScreenSettings *aThat)
    127126{
    128     LogFlowThisFuncEnter();
    129127    LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
    130128
     
    172170HRESULT RecordingScreenSettings::initCopy(RecordingSettings *aParent, RecordingScreenSettings *aThat)
    173171{
    174     LogFlowThisFuncEnter();
    175172    LogFlowThisFunc(("aParent: %p, aThat: %p\n", aParent, aThat));
    176173
     
    194191    m->bd.attachCopy(aThat->m->bd);
    195192
    196     HRESULT rc = S_OK;
     193    HRESULT hrc = S_OK;
    197194
    198195    int vrc = i_initInternal();
     
    204201    {
    205202        autoInitSpan.setFailed();
    206         rc = E_UNEXPECTED;
     203        hrc = E_UNEXPECTED;
    207204    }
    208205
    209206    LogFlowThisFuncLeave();
    210     return rc;
     207    return hrc;
    211208}
    212209
     
    331328
    332329    m->bd.backup();
     330
     331    settings::RecordingFeatureMap featureMapOld = m->bd->featureMap;
    333332    m->bd->featureMap.clear();
    334333
     
    338337        m->bd->featureMap[RecordingFeature_Video] = true;
    339338
    340     alock.release();
     339    if (m->bd->featureMap != featureMapOld)
     340    {
     341        alock.release();
     342
     343        m->pParent->i_onSettingsChanged();
     344    }
    341345
    342346    return S_OK;
     
    363367        return setError(E_INVALIDARG, tr("Cannot change destination type while recording is enabled"));
    364368
    365     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    366 
    367     m->bd.backup();
    368     m->bd->enmDest = aDestination;
     369    if (aDestination != RecordingDestination_File)
     370        return setError(E_INVALIDARG, tr("Destination type invalid / not supported"));
     371
     372    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     373
     374    if (m->bd->enmDest != aDestination)
     375    {
     376        m->bd.backup();
     377        m->bd->enmDest = aDestination;
     378
     379        m->pParent->i_onSettingsChanged();
     380    }
    369381
    370382    return S_OK;
     
    382394        || m->bd->File.strName.equals("."))
    383395    {
    384         int vrc = m->pParent->i_getDefaultFilename(m->bd->File.strName, true /* fWithFileExtension */);
     396        int vrc = m->pParent->i_getDefaultFilename(aFilename, m->uScreenId, true /* fWithFileExtension */);
    385397        if (RT_FAILURE(vrc))
    386             return setError(E_INVALIDARG, tr("Error retrieving default file name"));
    387     }
    388 
    389     aFilename = m->bd->File.strName;
     398            return setErrorBoth(E_INVALIDARG, vrc, tr("Error retrieving default file name"));
     399
     400        /* Important: Don't assign the default file name to File.strName, as this woulnd't be considered
     401         *            as default settings anymore! */
     402    }
     403    else /* Return custom file name. */
     404        aFilename = m->bd->File.strName;
    390405
    391406    return S_OK;
     
    400415        return setError(E_INVALIDARG, tr("Cannot change file name while recording is enabled"));
    401416
    402     Utf8Str strFile(aFilename);
    403     if (!RTPathStartsWithRoot(strFile.c_str()))
    404         return setError(E_INVALIDARG, tr("Recording file name '%s' is not absolute"), strFile.c_str());
    405 
    406     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    407 
    408     m->bd.backup();
    409     m->bd->File.strName = strFile;
     417    if (aFilename.isNotEmpty())
     418    {
     419        if (!RTPathStartsWithRoot(aFilename.c_str()))
     420            return setError(E_INVALIDARG, tr("Recording file name '%s' is not absolute"), aFilename.c_str());
     421    }
     422
     423    /** @todo Add more sanity? */
     424
     425    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     426
     427    /* Note: When setting an empty file name, this will return the screen's default file name when using ::getFileName(). */
     428    if (m->bd->File.strName != aFilename)
     429    {
     430        m->bd.backup();
     431        m->bd->File.strName = aFilename;
     432
     433        alock.release();
     434
     435        m->pParent->i_onSettingsChanged();
     436    }
    410437
    411438    return S_OK;
     
    434461    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    435462
    436     m->bd.backup();
    437     m->bd->ulMaxTimeS = aMaxTimeS;
     463    if (m->bd->ulMaxTimeS != aMaxTimeS)
     464    {
     465        m->bd.backup();
     466        m->bd->ulMaxTimeS = aMaxTimeS;
     467
     468        alock.release();
     469
     470        m->pParent->i_onSettingsChanged();
     471    }
    438472
    439473    return S_OK;
     
    462496    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    463497
    464     m->bd.backup();
    465     m->bd->File.ulMaxSizeMB = aMaxFileSize;
     498    if (m->bd->File.ulMaxSizeMB != aMaxFileSize)
     499    {
     500        m->bd.backup();
     501        m->bd->File.ulMaxSizeMB = aMaxFileSize;
     502
     503        alock.release();
     504
     505        m->pParent->i_onSettingsChanged();
     506    }
    466507
    467508    return S_OK;
     
    489530
    490531    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    491 
    492     m->bd.backup();
    493     m->bd->strOptions = aOptions;
    494532
    495533    int vrc = RecordingScreenSettings::i_parseOptionsString(aOptions, *m->bd.data());
     
    497535        return setError(E_INVALIDARG, tr("Invalid option specified"));
    498536
     537    m->bd.backup();
     538    m->bd->strOptions = aOptions;
     539
     540    alock.release();
     541
     542    m->pParent->i_onSettingsChanged();
     543
    499544    return S_OK;
    500545}
     
    520565        return setError(E_INVALIDARG, tr("Cannot change audio codec while recording is enabled"));
    521566
    522     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    523 
    524     m->bd.backup();
    525     m->bd->Audio.enmAudioCodec = aCodec;
     567    if (aCodec != RecordingAudioCodec_Opus)
     568        return setError(E_INVALIDARG, tr("Audio codec not supported"));
     569
     570    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     571
     572    if (m->bd->Audio.enmAudioCodec != aCodec)
     573    {
     574        m->bd.backup();
     575        m->bd->Audio.enmAudioCodec = aCodec;
     576
     577        alock.release();
     578
     579        m->pParent->i_onSettingsChanged();
     580    }
    526581
    527582    return S_OK;
     
    550605    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    551606
    552     m->bd.backup();
    553     m->bd->Audio.uHz = (uint16_t)aHz;
     607    if (m->bd->Audio.uHz != (uint16_t)aHz)
     608    {
     609        m->bd.backup();
     610        m->bd->Audio.uHz = (uint16_t)aHz;
     611
     612        alock.release();
     613
     614        m->pParent->i_onSettingsChanged();
     615    }
    554616
    555617    return S_OK;
     
    578640    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    579641
    580     m->bd.backup();
    581     m->bd->Audio.cBits = (uint8_t)aBits;
     642    if (m->bd->Audio.cBits != (uint8_t)aBits)
     643    {
     644        m->bd.backup();
     645        m->bd->Audio.cBits = (uint8_t)aBits;
     646
     647        alock.release();
     648
     649        m->pParent->i_onSettingsChanged();
     650    }
    582651
    583652    return S_OK;
     
    606675    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    607676
    608     m->bd.backup();
    609     m->bd->Audio.cChannels = (uint8_t)aChannels;
     677    if (m->bd->Audio.cChannels != (uint8_t)aChannels)
     678    {
     679        m->bd.backup();
     680        m->bd->Audio.cChannels = (uint8_t)aChannels;
     681
     682        alock.release();
     683
     684        m->pParent->i_onSettingsChanged();
     685    }
    610686
    611687    return S_OK;
     
    632708        return setError(E_INVALIDARG, tr("Cannot change video codec while recording is enabled"));
    633709
    634     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    635 
    636     m->bd.backup();
    637     m->bd->Video.enmCodec = aCodec;
     710    if (aCodec != RecordingVideoCodec_VP8)
     711        return setError(E_INVALIDARG, tr("Video codec not supported"));
     712
     713    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     714
     715    if (m->bd->Video.enmCodec != aCodec)
     716    {
     717        m->bd.backup();
     718        m->bd->Video.enmCodec = aCodec;
     719
     720        alock.release();
     721
     722        m->pParent->i_onSettingsChanged();
     723    }
    638724
    639725    return S_OK;
     
    662748    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    663749
    664     m->bd.backup();
    665     m->bd->Video.ulWidth = aVideoWidth;
     750    if (m->bd->Video.ulWidth != aVideoWidth)
     751    {
     752        m->bd.backup();
     753        m->bd->Video.ulWidth = aVideoWidth;
     754
     755        alock.release();
     756
     757        m->pParent->i_onSettingsChanged();
     758    }
    666759
    667760    return S_OK;
     
    690783    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    691784
    692     m->bd.backup();
    693     m->bd->Video.ulHeight = aVideoHeight;
     785    if (m->bd->Video.ulHeight != aVideoHeight)
     786    {
     787        m->bd.backup();
     788        m->bd->Video.ulHeight = aVideoHeight;
     789
     790        alock.release();
     791
     792        m->pParent->i_onSettingsChanged();
     793    }
    694794
    695795    return S_OK;
     
    718818    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    719819
    720     m->bd.backup();
    721     m->bd->Video.ulRate = aVideoRate;
     820    if (m->bd->Video.ulRate != aVideoRate)
     821    {
     822        m->bd.backup();
     823        m->bd->Video.ulRate = aVideoRate;
     824
     825        alock.release();
     826
     827        m->pParent->i_onSettingsChanged();
     828    }
    722829
    723830    return S_OK;
     
    774881    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    775882
    776     m->bd.backup();
    777     m->bd->Video.ulFPS = aVideoFPS;
     883    if (m->bd->Video.ulFPS != aVideoFPS)
     884    {
     885        m->bd.backup();
     886        m->bd->Video.ulFPS = aVideoFPS;
     887
     888        alock.release();
     889
     890        m->pParent->i_onSettingsChanged();
     891    }
    778892
    779893    return S_OK;
     
    811925 * Initializes data, internal version.
    812926 *
    813  * @returns IPRT status code.
     927 * @returns VBox status code.
    814928 */
    815929int RecordingScreenSettings::i_initInternal(void)
    816930{
    817     Assert(m);
    818 
    819     int rc = i_parseOptionsString(m->bd->strOptions, *m->bd.data());
    820     if (RT_FAILURE(rc))
    821         return rc;
     931    AssertPtrReturn(m, VERR_INVALID_POINTER);
     932
     933    int vrc = i_parseOptionsString(m->bd->strOptions, *m->bd.data());
     934    if (RT_FAILURE(vrc))
     935        return vrc;
    822936
    823937    switch (m->bd->enmDest)
     
    825939        case RecordingDestination_File:
    826940        {
    827             if (m->bd->File.strName.isEmpty())
    828                 rc = m->pParent->i_getDefaultFilename(m->bd->File.strName, true /* fWithExtension */);
     941            /* Note: Leave the file name empty here, which means using the default setting.
     942             *       Important when comparing with the default settings! */
    829943            break;
    830944        }
     
    834948    }
    835949
    836     return rc;
     950    return vrc;
     951}
     952
     953
     954// public methods only for internal purposes
     955////////////////////////////////////////////////////////////////////////////////
     956
     957/**
     958 * Loads settings from the given machine node.
     959 * May be called once right after this object creation.
     960 *
     961 * @returns HRESULT
     962 * @param   data                Configuration settings to load.
     963 */
     964HRESULT RecordingScreenSettings::i_loadSettings(const settings::RecordingScreenSettings &data)
     965{
     966    AutoCaller autoCaller(this);
     967    AssertComRCReturnRC(autoCaller.rc());
     968
     969    AutoReadLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
     970    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     971
     972    // simply copy
     973    m->bd.assignCopy(&data);
     974    return S_OK;
     975}
     976
     977/**
     978 *  Saves settings to the given machine node.
     979 *
     980 *  @returns HRESULT
     981 *  @param   data               Configuration settings to save to.
     982 */
     983HRESULT RecordingScreenSettings::i_saveSettings(settings::RecordingScreenSettings &data)
     984{
     985    /* sanity */
     986    AutoCaller autoCaller(this);
     987    AssertComRCReturnRC(autoCaller.rc());
     988
     989    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     990
     991    data = *m->bd.data();
     992
     993    return S_OK;
     994}
     995
     996void RecordingScreenSettings::i_rollback(void)
     997{
     998    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     999    m->bd.rollback();
     1000}
     1001
     1002void RecordingScreenSettings::i_commit(void)
     1003{
     1004    /* sanity */
     1005    AutoCaller autoCaller(this);
     1006    AssertComRCReturnVoid(autoCaller.rc());
     1007
     1008    /* sanity too */
     1009    AutoCaller peerCaller(m->pPeer);
     1010    AssertComRCReturnVoid(peerCaller.rc());
     1011
     1012    /* lock both for writing since we modify both (mPeer is "master" so locked
     1013     * first) */
     1014    AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
     1015
     1016    if (m->bd.isBackedUp())
     1017    {
     1018        m->bd.commit();
     1019        if (m->pPeer)
     1020        {
     1021            /* attach new data to the peer and reshare it */
     1022            AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
     1023            m->pPeer->m->bd.attach(m->bd);
     1024        }
     1025    }
     1026}
     1027
     1028void RecordingScreenSettings::i_copyFrom(RecordingScreenSettings *aThat)
     1029{
     1030    AssertReturnVoid(aThat != NULL);
     1031
     1032    /* sanity */
     1033    AutoCaller autoCaller(this);
     1034    AssertComRCReturnVoid(autoCaller.rc());
     1035
     1036    /* sanity too */
     1037    AutoCaller thatCaller(aThat);
     1038    AssertComRCReturnVoid(thatCaller.rc());
     1039
     1040    /* peer is not modified, lock it for reading (aThat is "master" so locked
     1041     * first) */
     1042    AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
     1043    AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
     1044
     1045    /* this will back up current data */
     1046    m->bd.assignCopy(aThat->m->bd);
     1047}
     1048
     1049/**
     1050 * Applies default screen recording settings.
     1051 *
     1052 * @note Locks this object for writing.
     1053 */
     1054void RecordingScreenSettings::i_applyDefaults(void)
     1055{
     1056    /* sanity */
     1057    AutoCaller autoCaller(this);
     1058    AssertComRCReturnVoid(autoCaller.rc());
     1059
     1060    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1061
     1062    m->bd->applyDefaults();
     1063}
     1064
     1065settings::RecordingScreenSettings &RecordingScreenSettings::i_getData(void)
     1066{
     1067    /* sanity */
     1068    AutoCaller autoCaller(this);
     1069    AssertComRC(autoCaller.rc());
     1070
     1071    AssertPtr(m);
     1072    return *m->bd.data();
    8371073}
    8381074
  • trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp

    r93115 r95639  
    4343    { }
    4444
    45     Machine * const                    pMachine;
    46     const ComObjPtr<RecordingSettings> pPeer;
    47     RecordScreenSettingsMap            mapScreenObj;
     45    Machine * const                         pMachine;
     46    const ComObjPtr<RecordingSettings>      pPeer;
     47    RecordingScreenSettingsObjMap           mapScreenObj;
    4848
    4949    // use the XML settings structure in the members for simplicity
    50     Backupable<settings::RecordingSettings> bd;
     50    Backupable<settings::RecordingCommonSettings> bd;
    5151};
    5252
     
    8787    m->bd.allocate();
    8888
     89    i_applyDefaults();
     90
    8991    autoInitSpan.setSucceeded();
    9092
     
    99101 *
    100102 *  @note This object must be destroyed before the original object
    101  *  it shares data with is destroyed.
     103 *        it shares data with is destroyed.
    102104 *
    103105 *  @note Locks @a aThat object for reading.
     
    157159
    158160    AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
    159 
    160161    m->bd.attachCopy(aThat->m->bd);
    161     m->mapScreenObj = aThat->m->mapScreenObj;
    162 
    163     autoInitSpan.setSucceeded();
     162
     163    HRESULT hrc = S_OK;
     164
     165    for (RecordingScreenSettingsObjMap::const_iterator itScreenThat  = aThat->m->mapScreenObj.begin();
     166                                                       itScreenThat != aThat->m->mapScreenObj.end();
     167                                                     ++itScreenThat)
     168    {
     169        ComObjPtr<RecordingScreenSettings> pSettings;
     170        pSettings.createObject();
     171        hrc = pSettings->initCopy(this, itScreenThat->second);
     172        if (FAILED(hrc)) return hrc;
     173
     174        try
     175        {
     176            m->mapScreenObj[itScreenThat->first] = pSettings;
     177        }
     178        catch (...)
     179        {
     180            hrc = E_OUTOFMEMORY;
     181        }
     182    }
     183
     184    if (SUCCEEDED(hrc))
     185        autoInitSpan.setSucceeded();
    164186
    165187    LogFlowThisFuncLeave();
    166     return S_OK;
     188    return hrc;
    167189}
    168190
     
    229251        {
    230252            /*
    231              * Normally we would do the actual change _after_ i_onCaptureChange() succeeded.
     253             * Normally we would do the actual change _after_ i_onRecordingChange() succeeded.
    232254             * We cannot do this because that function uses RecordSettings::GetEnabled to
    233255             * determine if it should start or stop capturing. Therefore we need to manually
     
    270292    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    271293
    272     aRecordScreenSettings.clear();
    273     aRecordScreenSettings.resize(m->mapScreenObj.size());
    274 
    275     RecordScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenObj.begin();
     294    HRESULT hrc = S_OK;
     295
     296    try
     297    {
     298        aRecordScreenSettings.clear();
     299        aRecordScreenSettings.resize(m->mapScreenObj.size());
     300    }
     301    catch (...)
     302    {
     303        hrc = E_OUTOFMEMORY;
     304    }
     305
     306    if (FAILED(hrc))
     307        return hrc;
     308
     309    RecordingScreenSettingsObjMap::const_iterator itScreenObj = m->mapScreenObj.begin();
    276310    size_t i = 0;
    277     while (itScreenSettings != m->mapScreenObj.end())
    278     {
    279         itScreenSettings->second.queryInterfaceTo(aRecordScreenSettings[i].asOutParam());
    280         Assert(aRecordScreenSettings[i].isNotNull());
     311    while (itScreenObj != m->mapScreenObj.end())
     312    {
     313        itScreenObj->second.queryInterfaceTo(aRecordScreenSettings[i].asOutParam());
     314        AssertBreakStmt(aRecordScreenSettings[i].isNotNull(), hrc = E_POINTER);
    281315        ++i;
    282         ++itScreenSettings;
     316        ++itScreenObj;
    283317    }
    284318
    285319    Assert(aRecordScreenSettings.size() == m->mapScreenObj.size());
    286320
    287     return S_OK;
     321    return hrc;
    288322}
    289323
     
    306340        return setError(E_INVALIDARG, tr("Invalid screen ID specified"));
    307341
    308     RecordScreenSettingsMap::const_iterator itScreenSettings = m->mapScreenObj.find(uScreenId);
    309     if (itScreenSettings != m->mapScreenObj.end())
    310     {
    311         itScreenSettings->second.queryInterfaceTo(aRecordScreenSettings.asOutParam());
     342    RecordingScreenSettingsObjMap::const_iterator itScreen = m->mapScreenObj.find(uScreenId);
     343    if (itScreen != m->mapScreenObj.end())
     344    {
     345        itScreen->second.queryInterfaceTo(aRecordScreenSettings.asOutParam());
    312346        return S_OK;
    313347    }
     
    327361 * @returns IPRT status code. VERR_ALREADY_EXISTS if the object in question already exists.
    328362 * @param   screenSettingsMap   Map to add screen settings to.
    329  * @param   uScreenId           Screen ID to add settings for.
     363 * @param   idScreen            Screen ID to add settings for.
    330364 * @param   data                Recording screen settings to use for that screen.
    331365 */
    332 int RecordingSettings::i_createScreenObj(RecordScreenSettingsMap &screenSettingsMap,
    333                                        uint32_t uScreenId, const settings::RecordingScreenSettings &data)
    334 {
    335     LogFlowThisFunc(("Screen %RU32\n", uScreenId));
    336 
    337     if (screenSettingsMap.find(uScreenId) != screenSettingsMap.end())
    338     {
    339         AssertFailed();
    340         return VERR_ALREADY_EXISTS;
    341     }
     366int RecordingSettings::i_createScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap,
     367                                         uint32_t idScreen, const settings::RecordingScreenSettings &data)
     368{
     369    AssertReturn(screenSettingsMap.find(idScreen) == screenSettingsMap.end(), VERR_ALREADY_EXISTS);
     370
     371    LogFlowThisFunc(("Screen %RU32\n", idScreen));
    342372
    343373    int vrc = VINF_SUCCESS;
    344374
    345375    ComObjPtr<RecordingScreenSettings> recordingScreenSettings;
    346     HRESULT rc = recordingScreenSettings.createObject();
    347     if (SUCCEEDED(rc))
    348     {
    349         rc = recordingScreenSettings->init(this, uScreenId, data);
    350         if (SUCCEEDED(rc))
     376    HRESULT hrc = recordingScreenSettings.createObject();
     377    if (SUCCEEDED(hrc))
     378    {
     379        hrc = recordingScreenSettings->init(this, idScreen, data);
     380        if (SUCCEEDED(hrc))
    351381        {
    352382            try
    353383            {
    354                 screenSettingsMap[uScreenId] = recordingScreenSettings;
     384                screenSettingsMap[idScreen] = recordingScreenSettings;
    355385            }
    356386            catch (std::bad_alloc &)
     
    369399 * @returns IPRT status code. VERR_NOT_FOUND if specified screen was not found.
    370400 * @param   screenSettingsMap   Map to remove screen settings from.
    371  * @param   uScreenId           ID of screen to remove.
    372  */
    373 int RecordingSettings::i_destroyScreenObj(RecordScreenSettingsMap &screenSettingsMap, uint32_t uScreenId)
    374 {
    375     LogFlowThisFunc(("Screen %RU32\n", uScreenId));
    376 
    377     AssertReturn(uScreenId > 0, VERR_INVALID_PARAMETER); /* Removing screen 0 isn't a good idea. */
    378 
    379     RecordScreenSettingsMap::iterator itScreen = screenSettingsMap.find(uScreenId);
    380     if (itScreen == screenSettingsMap.end())
    381     {
    382         AssertFailed();
    383         return VERR_NOT_FOUND;
    384     }
     401 * @param   idScreen            ID of screen to remove.
     402 */
     403int RecordingSettings::i_destroyScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap, uint32_t idScreen)
     404{
     405    LogFlowThisFunc(("Screen %RU32\n", idScreen));
     406
     407    AssertReturn(idScreen > 0, VERR_INVALID_PARAMETER); /* Removing screen 0 isn't a good idea. */
     408    AssertReturn(screenSettingsMap.find(idScreen) == screenSettingsMap.end(), VERR_NOT_FOUND);
     409
     410    RecordingScreenSettingsObjMap::iterator itScreen = screenSettingsMap.find(idScreen);
    385411
    386412    /* Make sure to consume the pointer before the one of the
     
    401427 * @param   screenSettingsMap   Map to destroy screen settings objects for.
    402428 */
    403 int RecordingSettings::i_destroyAllScreenObj(RecordScreenSettingsMap &screenSettingsMap)
    404 {
    405     LogFlowThisFuncEnter();
    406 
    407     RecordScreenSettingsMap::iterator itScreen = screenSettingsMap.begin();
    408     while (itScreen != screenSettingsMap.end())
     429int RecordingSettings::i_destroyAllScreenObj(RecordingScreenSettingsObjMap &screenSettingsMap)
     430{
     431    LogFlowThisFuncEnter();
     432
     433    RecordingScreenSettingsObjMap::iterator itScreenObj = screenSettingsMap.begin();
     434    while (itScreenObj != screenSettingsMap.end())
    409435    {
    410436        /* Make sure to consume the pointer before the one of the
    411437         * iterator gets released. */
    412         ComObjPtr<RecordingScreenSettings> pScreenSettings = itScreen->second;
    413 
    414         screenSettingsMap.erase(itScreen);
    415 
     438        ComObjPtr<RecordingScreenSettings> pScreenSettings = itScreenObj->second;
     439
     440        screenSettingsMap.erase(itScreenObj);
     441
     442        pScreenSettings->uninit();
    416443        pScreenSettings.setNull();
    417444
    418         itScreen = screenSettingsMap.begin();
     445        itScreenObj = screenSettingsMap.begin();
    419446    }
    420447
     
    440467    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    441468
    442     HRESULT rc = S_OK;
    443 
    444     i_reset();
     469    HRESULT hrc = S_OK;
    445470
    446471    LogFlowThisFunc(("Data has %zu screens\n", data.mapScreens.size()));
    447472
    448     settings::RecordingScreenMap::const_iterator itScreen = data.mapScreens.begin();
    449     while (itScreen != data.mapScreens.end())
    450     {
    451         int vrc = i_createScreenObj(m->mapScreenObj,
    452                                     itScreen->first /* uScreenId */, itScreen->second /* Settings */);
    453         if (RT_FAILURE(vrc))
    454         {
    455             rc = E_OUTOFMEMORY;
    456             break;
    457         }
    458 
    459         ++itScreen;
    460     }
    461 
    462     if (FAILED(rc))
    463         return rc;
    464 
    465     ComAssertComRC(rc);
    466     Assert(m->mapScreenObj.size() == data.mapScreens.size());
    467 
    468     // simply copy
    469     m->bd.assignCopy(&data);
    470 
    471     LogFlowThisFunc(("Returning %Rhrc\n", rc));
    472     return rc;
     473    settings::RecordingScreenSettingsMap::const_iterator itScreenData = data.mapScreens.begin();
     474    while (itScreenData != data.mapScreens.end())
     475    {
     476        RecordingScreenSettingsObjMap::iterator itScreen = m->mapScreenObj.find(itScreenData->first);
     477        if (itScreen != m->mapScreenObj.end())
     478        {
     479            hrc = itScreen->second->i_loadSettings(itScreenData->second);
     480            if (FAILED(hrc))
     481                break;
     482        }
     483        else
     484        {
     485            int vrc = i_createScreenObj(m->mapScreenObj,
     486                                        itScreenData->first /* uScreenId */, itScreenData->second /* Settings */);
     487            if (RT_FAILURE(vrc))
     488            {
     489                hrc = E_OUTOFMEMORY; /* Most likely. */
     490                break;
     491            }
     492        }
     493
     494        ++itScreenData;
     495    }
     496
     497    if (SUCCEEDED(hrc))
     498    {
     499        ComAssertComRCRet(hrc, hrc);
     500        AssertReturn(m->mapScreenObj.size() == data.mapScreens.size(), E_UNEXPECTED);
     501
     502        // simply copy
     503        m->bd.assignCopy(&data.common);
     504    }
     505
     506    LogFlowThisFunc(("Returning %Rhrc\n", hrc));
     507    return hrc;
    473508}
    474509
     
    481516
    482517    i_destroyAllScreenObj(m->mapScreenObj);
    483     m->bd->mapScreens.clear();
    484518}
    485519
     
    510544    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    511545
    512     data = *m->bd.data();
    513 
    514     settings::RecordingScreenMap::iterator itScreen = data.mapScreens.begin();
    515     while (itScreen != data.mapScreens.end())
    516     {
    517         /* Store relative path of capture file if possible. */
    518         m->pMachine->i_copyPathRelativeToMachine(itScreen->second.File.strName /* Source */,
    519                                                  itScreen->second.File.strName /* Target */);
    520         ++itScreen;
     546    data.common = *m->bd.data();
     547
     548    HRESULT hrc;
     549
     550    for (RecordingScreenSettingsObjMap::const_iterator itScreen  = m->mapScreenObj.begin();
     551                                                       itScreen != m->mapScreenObj.end();
     552                                                     ++itScreen)
     553    {
     554        hrc = itScreen->second->i_saveSettings(data.mapScreens[itScreen->first /* Screen ID */]);
     555        if (FAILED(hrc))
     556            break;
    521557    }
    522558
    523559    LogFlowThisFuncLeave();
    524     return S_OK;
    525 }
    526 
    527 void RecordingSettings::i_rollback()
     560    return hrc;
     561}
     562
     563void RecordingSettings::i_rollback(void)
    528564{
    529565    /* sanity */
     
    532568
    533569    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     570
    534571    m->bd.rollback();
    535 }
    536 
    537 void RecordingSettings::i_commit()
     572
     573    for (RecordingScreenSettingsObjMap::const_iterator itScreen  = m->mapScreenObj.begin();
     574                                                       itScreen != m->mapScreenObj.end();
     575                                                     ++itScreen)
     576    {
     577        itScreen->second->i_rollback();
     578    }
     579}
     580
     581void RecordingSettings::i_commit(void)
    538582{
    539583    /* sanity */
     
    557601            m->pPeer->m->bd.attach(m->bd);
    558602        }
    559     }
    560 }
    561 
    562 void RecordingSettings::i_copyFrom(RecordingSettings *aThat)
    563 {
    564     AssertReturnVoid(aThat != NULL);
     603
     604        for (RecordingScreenSettingsObjMap::const_iterator itScreenObj  = m->mapScreenObj.begin();
     605                                                           itScreenObj != m->mapScreenObj.end();
     606                                                         ++itScreenObj)
     607        {
     608            itScreenObj->second->i_commit();
     609            if (m->pPeer)
     610                m->pPeer->i_commit();
     611        }
     612    }
     613}
     614
     615HRESULT RecordingSettings::i_copyFrom(RecordingSettings *aThat)
     616{
     617    AssertPtrReturn(aThat, E_INVALIDARG);
    565618
    566619    /* sanity */
    567620    AutoCaller autoCaller(this);
    568     AssertComRCReturnVoid(autoCaller.rc());
     621    AssertComRCReturn(autoCaller.rc(), VBOX_E_INVALID_OBJECT_STATE);
    569622
    570623    /* sanity too */
    571624    AutoCaller thatCaller(aThat);
    572     AssertComRCReturnVoid(thatCaller.rc());
     625    AssertComRCReturn(thatCaller.rc(), VBOX_E_INVALID_OBJECT_STATE);
    573626
    574627    /* peer is not modified, lock it for reading (aThat is "master" so locked
     
    579632    /* this will back up current data */
    580633    m->bd.assignCopy(aThat->m->bd);
     634
     635    HRESULT hrc = S_OK;
     636
     637    for (RecordingScreenSettingsObjMap::const_iterator itScreenThat  = aThat->m->mapScreenObj.begin();
     638                                                       itScreenThat != aThat->m->mapScreenObj.end();
     639                                                     ++itScreenThat)
     640    {
     641        RecordingScreenSettingsObjMap::iterator itScreen = m->mapScreenObj.find(itScreenThat->first);
     642        if (itScreen != m->mapScreenObj.end())
     643        {
     644            itScreen->second->i_copyFrom(itScreenThat->second);
     645        }
     646        else
     647        {
     648            int vrc = i_createScreenObj(m->mapScreenObj,
     649                                        itScreenThat->first /* uScreenId */, itScreenThat->second->i_getData() /* Settings */);
     650            if (RT_FAILURE(vrc))
     651            {
     652                hrc = E_OUTOFMEMORY; /* Most likely. */
     653                break;
     654            }
     655        }
     656    }
     657
     658    return hrc;
    581659}
    582660
     
    606684
    607685/**
    608  * Returns the full path to the default video capture file.
    609  */
    610 int RecordingSettings::i_getDefaultFilename(Utf8Str &strFile, bool fWithFileExtension)
     686 * Returns the full path to the default recording file.
     687 */
     688int RecordingSettings::i_getDefaultFilename(Utf8Str &strFile, uint32_t idScreen, bool fWithFileExtension)
    611689{
    612690    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    613691
    614692    strFile = m->pMachine->i_getSettingsFileFull(); // path/to/machinesfolder/vmname/vmname.vbox
    615     strFile.stripSuffix();                          // path/to/machinesfolder/vmname/vmname
     693    strFile.stripSuffix();
     694    strFile.append(Utf8StrFmt("-screen%RU32", idScreen));
    616695    if (fWithFileExtension)
    617         strFile.append(".webm");                    // path/to/machinesfolder/vmname/vmname.webm
     696        strFile.append(".webm");
    618697
    619698    return VINF_SUCCESS;
     
    661740 * Synchronizes the screen settings (COM) objects and configuration data
    662741 * to the number of the machine's configured displays.
    663  */
    664 int RecordingSettings::i_syncToMachineDisplays(uint32_t cMonitors)
     742 *
     743 * Note: This function ASSUMES that we always have configured VM displays
     744 *       as a consequtive sequence with no holes in between.
     745 */
     746int RecordingSettings::i_syncToMachineDisplays(uint32_t cDisplays)
    665747{
    666748    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    667749
    668     LogFlowThisFunc(("cMonitors=%RU32\n", cMonitors));
    669     LogFlowThisFunc(("Data screen count = %zu, COM object count = %zu\n", m->bd->mapScreens.size(), m->mapScreenObj.size()));
    670 
    671750    /* If counts match, take a shortcut. */
    672     if (cMonitors == m->mapScreenObj.size())
     751    if (cDisplays == m->mapScreenObj.size())
    673752        return VINF_SUCCESS;
    674753
    675754    /* Create all new screen settings objects which are not there yet. */
    676     for (ULONG i = 0; i < cMonitors; i++)
     755    for (ULONG i = 0; i < cDisplays; i++)
    677756    {
    678757        if (m->mapScreenObj.find(i) == m->mapScreenObj.end())
    679758        {
    680             settings::RecordingScreenMap::const_iterator itScreen = m->bd->mapScreens.find(i);
    681             if (itScreen == m->bd->mapScreens.end())
    682             {
    683                 settings::RecordingScreenSettings defaultScreenSettings; /* Apply default settings. */
    684                 m->bd->mapScreens[i] = defaultScreenSettings;
    685             }
    686 
    687             int vrc2 = i_createScreenObj(m->mapScreenObj, i /* Screen ID */, m->bd->mapScreens[i]);
     759            settings::RecordingScreenSettings defaultScreenSettings; /* Apply default settings. */
     760
     761            int vrc2 = i_createScreenObj(m->mapScreenObj, i /* Screen ID */, defaultScreenSettings);
    688762            AssertRC(vrc2);
    689763        }
     
    691765
    692766    /* Remove all left over screen settings objects which are not needed anymore. */
    693     const ULONG cSettings = (ULONG)m->mapScreenObj.size();
    694     for (ULONG i = cMonitors; i < cSettings; i++)
    695     {
    696         m->bd->mapScreens.erase(i);
     767    for (ULONG i = cDisplays; i < (ULONG)m->mapScreenObj.size(); i++)
     768    {
    697769        int vrc2 = i_destroyScreenObj(m->mapScreenObj, i /* Screen ID */);
    698770        AssertRC(vrc2);
    699771    }
    700772
    701     Assert(m->mapScreenObj.size() == cMonitors);
    702     Assert(m->bd->mapScreens.size() == cMonitors);
     773    Assert(m->mapScreenObj.size() == cDisplays);
    703774
    704775    LogFlowThisFuncLeave();
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r95476 r95639  
    867867        data.strStateFile.setNull();
    868868
    869     HRESULT rc = m->pMachine->i_saveHardware(data.hardware, &data.debugging, &data.autostart);
    870     if (FAILED(rc)) return rc;
    871 
    872     return S_OK;
     869    return m->pMachine->i_saveHardware(data.hardware, &data.debugging, &data.autostart, data.recordingSettings);
    873870}
    874871
     
    11641161    if (FAILED(rc)) return rc;
    11651162
     1163    unconst(mRecordingSettings).createObject();
     1164    rc = mRecordingSettings->initCopy(this, pMachine->mRecordingSettings);
     1165    if (FAILED(rc)) return rc;
     1166
    11661167    unconst(mTrustedPlatformModule).createObject();
    11671168    rc = mTrustedPlatformModule->initCopy(this, pMachine->mTrustedPlatformModule);
     
    11701171    unconst(mNvramStore).createObject();
    11711172    rc = mNvramStore->initCopy(this, pMachine->mNvramStore);
    1172     if (FAILED(rc)) return rc;
    1173 
    1174     unconst(mRecordingSettings).createObject();
    1175     rc = mRecordingSettings->initCopy(this, pMachine->mRecordingSettings);
    11761173    if (FAILED(rc)) return rc;
    11771174
     
    12471244 *  @param pDbg             debuging settings
    12481245 *  @param pAutostart       autostart settings
     1246 *  @param recording        recording settings
    12491247 *  @param aSnapshotId      snapshot ID of this snapshot machine
    12501248 *  @param aStateFilePath   file where the execution state is saved
     
    12571255                                          const settings::Debugging *pDbg,
    12581256                                          const settings::Autostart *pAutostart,
     1257                                          const settings::RecordingSettings &recording,
    12591258                                          IN_GUID aSnapshotId,
    12601259                                          const Utf8Str &aStateFilePath)
     
    13021301    mBIOSSettings->init(this);
    13031302
     1303    unconst(mRecordingSettings).createObject();
     1304    mRecordingSettings->init(this);
     1305
    13041306    unconst(mTrustedPlatformModule).createObject();
    13051307    mTrustedPlatformModule->init(this);
     
    13081310    mNvramStore->init(this);
    13091311
    1310     unconst(mRecordingSettings).createObject();
    1311     mRecordingSettings->init(this);
    1312 
    13131312    unconst(mGraphicsAdapter).createObject();
    13141313    mGraphicsAdapter->init(this);
     
    13461345
    13471346    /* load hardware and storage settings */
    1348     HRESULT rc = i_loadHardware(NULL, &mSnapshotId, hardware, pDbg, pAutostart);
    1349 
    1350     if (SUCCEEDED(rc))
     1347    HRESULT hrc = i_loadHardware(NULL, &mSnapshotId, hardware, pDbg, pAutostart, recording);
     1348    if (SUCCEEDED(hrc))
    13511349        /* commit all changes made during the initialization */
    13521350        i_commit();   /// @todo r=dj why do we need a commit in init?!? this is very expensive
     
    13551353
    13561354    /* Confirm a successful initialization when it's the case */
    1357     if (SUCCEEDED(rc))
     1355    if (SUCCEEDED(hrc))
    13581356        autoInitSpan.setSucceeded();
    13591357
    13601358    LogFlowThisFuncLeave();
    1361     return rc;
     1359    return hrc;
    13621360}
    13631361
  • trunk/src/VBox/Main/xml/Settings.cpp

    r95395 r95639  
    27792779
    27802780/**
     2781 * Returns the default options string for screen recording settings.
     2782 */
     2783/* static */
     2784const char *RecordingScreenSettings::getDefaultOptions(void)
     2785{
     2786    /* Note: Needs to be kept in sync with FE/Qt's UIMachineSettingsDisplay::putToCache()! */
     2787    return "vc_enabled=true,ac_enabled=false,ac_profile=med";
     2788}
     2789
     2790/**
    27812791 * Applies the default settings.
    27822792 */
     
    27872797     */
    27882798
    2789     fEnabled            = false;
    2790     enmDest             = RecordingDestination_File;
    2791     ulMaxTimeS          = 0;
    2792     strOptions          = "";
    2793     File.ulMaxSizeMB    = 0;
    2794     File.strName        = "";
    2795     Video.enmCodec      = RecordingVideoCodec_VP8;
    2796     Video.ulWidth       = 1024;
    2797     Video.ulHeight      = 768;
    2798     Video.ulRate        = 512;
    2799     Video.ulFPS         = 25;
    2800     Audio.enmAudioCodec = RecordingAudioCodec_Opus;
    2801     Audio.cBits         = 16;
    2802     Audio.cChannels     = 2;
    2803     Audio.uHz           = 22050;
     2799    fEnabled             = false;
     2800    enmDest              = RecordingDestination_File;
     2801    ulMaxTimeS           = 0;
     2802    strOptions           = RecordingScreenSettings::getDefaultOptions();
     2803    File.ulMaxSizeMB     = 0;
     2804    File.strName         = "";
     2805    Video.enmCodec       = RecordingVideoCodec_VP8;
     2806    Video.ulWidth        = 1024;
     2807    Video.ulHeight       = 768;
     2808    Video.ulRate         = 512;
     2809    Video.ulFPS          = 25;
     2810    Audio.enmAudioCodec  = RecordingAudioCodec_Opus;
     2811    Audio.cBits          = 16;
     2812    Audio.cChannels      = 2;
     2813    Audio.uHz            = 22050;
    28042814
    28052815    featureMap[RecordingFeature_Video] = true;
     
    28122822bool RecordingScreenSettings::areDefaultSettings(void) const
    28132823{
    2814     return    fEnabled            == false
    2815            && enmDest             == RecordingDestination_File
    2816            && ulMaxTimeS          == 0
    2817            && strOptions          == ""
    2818            && File.ulMaxSizeMB    == 0
    2819            && File.strName        == ""
    2820            && Video.enmCodec      == RecordingVideoCodec_VP8
    2821            && Video.ulWidth       == 1024
    2822            && Video.ulHeight      == 768
    2823            && Video.ulRate        == 512
    2824            && Video.ulFPS         == 25
    2825            && Audio.enmAudioCodec == RecordingAudioCodec_Opus
    2826            && Audio.cBits         == 16
    2827            && Audio.cChannels     == 2
    2828            && Audio.uHz           == 22050;
     2824    return    fEnabled                                        == false
     2825           && enmDest                                         == RecordingDestination_File
     2826           && ulMaxTimeS                                      == 0
     2827           && strOptions                                      == RecordingScreenSettings::getDefaultOptions()
     2828           && File.ulMaxSizeMB                                == 0
     2829           && File.strName                                    == ""
     2830           && Video.enmCodec                                  == RecordingVideoCodec_VP8
     2831           && Video.ulWidth                                   == 1024
     2832           && Video.ulHeight                                  == 768
     2833           && Video.ulRate                                    == 512
     2834           && Video.ulFPS                                     == 25
     2835           && Audio.enmAudioCodec                             == RecordingAudioCodec_Opus
     2836           && Audio.cBits                                     == 16
     2837           && Audio.cChannels                                 == 2
     2838           && Audio.uHz                                       == 22050
     2839           && featureMap.find(RecordingFeature_Video)->second == true
     2840           && featureMap.find(RecordingFeature_Audio)->second == false;
    28292841}
    28302842
     
    28562868           && ulMaxTimeS          == d.ulMaxTimeS
    28572869           && strOptions          == d.strOptions
     2870           && File.strName        == d.File.strName
    28582871           && File.ulMaxSizeMB    == d.File.ulMaxSizeMB
    28592872           && Video.enmCodec      == d.Video.enmCodec
     
    28652878           && Audio.cBits         == d.Audio.cBits
    28662879           && Audio.cChannels     == d.Audio.cChannels
    2867            && Audio.uHz           == d.Audio.uHz;
     2880           && Audio.uHz           == d.Audio.uHz
     2881           && featureMap          == d.featureMap;
    28682882}
    28692883
     
    28712885 * Constructor. Needs to set sane defaults which stand the test of time.
    28722886 */
    2873 RecordingSettings::RecordingSettings()
     2887RecordingCommonSettings::RecordingCommonSettings()
    28742888{
    28752889    applyDefaults();
     
    28792893 * Applies the default settings.
    28802894 */
    2881 void RecordingSettings::applyDefaults(void)
     2895void RecordingCommonSettings::applyDefaults(void)
    28822896{
    28832897    fEnabled = false;
    2884 
    2885     mapScreens.clear();
    2886 
    2887     try
    2888     {
    2889         /* Always add screen 0 to the default configuration. */
    2890         RecordingScreenSettings screenSettings; /* Apply default settings for screen 0. */
    2891         screenSettings.fEnabled = true;       /* Enabled by default. */
    2892         mapScreens[0] = screenSettings;
    2893     }
    2894     catch (std::bad_alloc &)
    2895     {
    2896         AssertFailed();
    2897     }
    28982898}
    28992899
     
    29012901 * Check if all settings have default values.
    29022902 */
    2903 bool RecordingSettings::areDefaultSettings() const
    2904 {
    2905     const bool fDefault =    fEnabled          == false
    2906                           && mapScreens.size() == 1;
    2907     if (!fDefault)
    2908         return false;
    2909 
    2910     RecordingScreenMap::const_iterator itScreen = mapScreens.begin();
    2911     return    itScreen->first == 0
    2912            && itScreen->second.areDefaultSettings();
     2903bool RecordingCommonSettings::areDefaultSettings(void) const
     2904{
     2905    return fEnabled == false;
    29132906}
    29142907
     
    29182911 * machine settings have really changed and thus need to be written out to disk.
    29192912 */
    2920 bool RecordingSettings::operator==(const RecordingSettings &d) const
     2913bool RecordingCommonSettings::operator==(const RecordingCommonSettings &d) const
    29212914{
    29222915    if (this == &d)
    29232916        return true;
    29242917
    2925     if (   fEnabled          != d.fEnabled
    2926         || mapScreens.size() != d.mapScreens.size())
     2918    return fEnabled == d.fEnabled;
     2919}
     2920
     2921/**
     2922 * Constructor. Needs to set sane defaults which stand the test of time.
     2923 */
     2924RecordingSettings::RecordingSettings()
     2925{
     2926    applyDefaults();
     2927}
     2928
     2929/**
     2930 * Applies the default settings.
     2931 */
     2932void RecordingSettings::applyDefaults(void)
     2933{
     2934    common.applyDefaults();
     2935
     2936    mapScreens.clear();
     2937
     2938    try
     2939    {
     2940        /* Always add screen 0 to the default configuration. */
     2941        RecordingScreenSettings screenSettings;
     2942        mapScreens[0] = screenSettings;
     2943    }
     2944    catch (std::bad_alloc &)
     2945    {
     2946        AssertFailed();
     2947    }
     2948}
     2949
     2950/**
     2951 * Check if all settings have default values.
     2952 */
     2953bool RecordingSettings::areDefaultSettings(void) const
     2954{
     2955    AssertReturn(mapScreens.size() >= 1, false); /* The first screen always must be present. */
     2956
     2957    if (!common.areDefaultSettings())
    29272958        return false;
    29282959
    2929     RecordingScreenMap::const_iterator itScreen = mapScreens.begin();
    2930     uint32_t i = 0;
     2960    RecordingScreenSettingsMap::const_iterator itScreen = mapScreens.begin();
    29312961    while (itScreen != mapScreens.end())
    29322962    {
    2933         RecordingScreenMap::const_iterator itScreenThat = d.mapScreens.find(i);
     2963        if (!itScreen->second.areDefaultSettings())
     2964            return false;
     2965        ++itScreen;
     2966    }
     2967
     2968    return true;
     2969}
     2970
     2971/**
     2972 * Comparison operator. This gets called from MachineConfigFile::operator==,
     2973 * which in turn gets called from Machine::saveSettings to figure out whether
     2974 * machine settings have really changed and thus need to be written out to disk.
     2975 */
     2976bool RecordingSettings::operator==(const RecordingSettings &that) const
     2977{
     2978    if (this == &that) /* If pointers match, take a shortcut. */
     2979        return true;
     2980
     2981    if (common == that.common)
     2982    {
     2983        /* Too lazy for a != operator. */
     2984    }
     2985    else
     2986        return false;
     2987
     2988    if (mapScreens.size() != that.mapScreens.size())
     2989        return false;
     2990
     2991    RecordingScreenSettingsMap::const_iterator itScreen     = mapScreens.begin();
     2992    RecordingScreenSettingsMap::const_iterator itScreenThat = that.mapScreens.begin();
     2993    while (   itScreen     != mapScreens.end()
     2994           && itScreenThat != that.mapScreens.end())
     2995    {
    29342996        if (itScreen->second == itScreenThat->second)
    29352997        {
     
    29403002
    29413003        ++itScreen;
    2942         ++i;
     3004        ++itScreenThat;
    29433005    }
    29443006
     
    39343996            && strStateFile          == s.strStateFile
    39353997            && hardware              == s.hardware                  // deep compare
     3998            && recordingSettings     == s.recordingSettings         // deep compare
    39363999            && llChildSnapshots      == s.llChildSnapshots          // deep compare
    39374000            && debugging             == s.debugging
     
    41144177            // skip mapExtraDataItems! there is no old state available as it's always forced
    41154178            && llFirstSnapshot            == c.llFirstSnapshot     // this one's deep
     4179            && recordingSettings          == c.recordingSettings   // this one's deep
    41164180            && strKeyId                   == c.strKeyId
    41174181            && strKeyStore                == c.strKeyStore
     
    47144778 * the IDE and SATA controllers used to be defined under \<Hardware\>.
    47154779 *
    4716  * @param elmHardware
    4717  * @param hw
     4780 * @param elmHardware           Hardware node to read from.
     4781 * @param hw                    Where to store the hardware settings.
    47184782 */
    47194783void MachineConfigFile::readHardware(const xml::ElementNode &elmHardware,
     
    50785142                pelmHwChild->getAttributeValue("Accelerate3D", hw.graphicsAdapter.fAccelerate3D);   // pre-v1.5 variant
    50795143            pelmHwChild->getAttributeValue("accelerate2DVideo", hw.graphicsAdapter.fAccelerate2DVideo);
    5080         }
    5081         else if (pelmHwChild->nameEquals("VideoCapture"))
    5082         {
    5083             pelmHwChild->getAttributeValue("enabled",   hw.recordingSettings.fEnabled);
    5084 
    5085             /* Right now I don't want to bump the settings version, so just convert the enabled
    5086              * screens to the former uint64t_t bit array and vice versa. */
    5087             uint64_t u64VideoCaptureScreens;
    5088             pelmHwChild->getAttributeValue("screens",   u64VideoCaptureScreens);
    5089 
    5090             /* At the moment we only support one capturing configuration, that is, all screens
    5091              * have the same configuration. So load/save to/from screen 0. */
    5092             Assert(hw.recordingSettings.mapScreens.size()); /* At least screen must be present. */
    5093             RecordingScreenSettings &screen0Settings = hw.recordingSettings.mapScreens[0];
    5094 
    5095             pelmHwChild->getAttributeValue("maxTime",   screen0Settings.ulMaxTimeS);
    5096             pelmHwChild->getAttributeValue("options",   screen0Settings.strOptions);
    5097             pelmHwChild->getAttributeValuePath("file",  screen0Settings.File.strName);
    5098             pelmHwChild->getAttributeValue("maxSize",   screen0Settings.File.ulMaxSizeMB);
    5099             pelmHwChild->getAttributeValue("horzRes",   screen0Settings.Video.ulWidth);
    5100             pelmHwChild->getAttributeValue("vertRes",   screen0Settings.Video.ulHeight);
    5101             pelmHwChild->getAttributeValue("rate",      screen0Settings.Video.ulRate);
    5102             pelmHwChild->getAttributeValue("fps",       screen0Settings.Video.ulFPS);
    5103 
    5104             for (unsigned i = 0; i < hw.graphicsAdapter.cMonitors; i++) /* Don't add more settings than we have monitors configured. */
    5105             {
    5106                 /* Add screen i to config in any case. */
    5107                 hw.recordingSettings.mapScreens[i] = screen0Settings;
    5108 
    5109                 if (u64VideoCaptureScreens & RT_BIT_64(i)) /* Screen i enabled? */
    5110                     hw.recordingSettings.mapScreens[i].fEnabled = true;
    5111             }
    51125144        }
    51135145        else if (pelmHwChild->nameEquals("RemoteDisplay"))
     
    59495981
    59505982/**
     5983 * Called for reading the \<VideoCapture\> element under \<Machine|Hardware\>,
     5984 * or \<Recording\> under \<Machine\>,
     5985 */
     5986void MachineConfigFile::readRecordingSettings(const xml::ElementNode &elmRecording, RecordingSettings &recording)
     5987{
     5988    elmRecording.getAttributeValue("enabled", recording.common.fEnabled);
     5989
     5990    /* Note: Since settings 1.19 the recording settings have a dedicated XML branch "Recording" outside of "Hardware". */
     5991    if (m->sv >= SettingsVersion_v1_19 /* VBox >= 7.0 */)
     5992    {
     5993        uint32_t cScreens = 0;
     5994        elmRecording.getAttributeValue("screens",   cScreens);
     5995
     5996        xml::ElementNodesList plstScreens;
     5997        elmRecording.getChildElements(plstScreens, "Screen");
     5998
     5999        /* Sanity checks. */
     6000        if (cScreens != plstScreens.size())
     6001            throw ConfigFileError(this, &elmRecording, N_("Recording/@screens attribute does not match stored screen objects"));
     6002
     6003        for (xml::ElementNodesList::iterator itScreen  = plstScreens.begin();
     6004                                             itScreen != plstScreens.end();
     6005                                           ++itScreen)
     6006        {
     6007            /* The screen's stored ID is the monitor ID and also the key for the map. */
     6008            uint32_t idxScreen;
     6009            (*itScreen)->getAttributeValue("id",        idxScreen);
     6010
     6011            RecordingScreenSettings &screenSettings = recording.mapScreens[idxScreen];
     6012
     6013            (*itScreen)->getAttributeValue("enabled",   screenSettings.fEnabled);
     6014            (*itScreen)->getAttributeValue("maxTimeS",  screenSettings.ulMaxTimeS);
     6015            (*itScreen)->getAttributeValue("options",   screenSettings.strOptions);
     6016            (*itScreen)->getAttributeValue("dest",      (uint32_t &)screenSettings.enmDest);
     6017            if (screenSettings.enmDest == RecordingDestination_File)
     6018                (*itScreen)->getAttributeValuePath("file",  screenSettings.File.strName);
     6019            else
     6020                throw ConfigFileError(this, (*itScreen),
     6021                                      N_("Not supported Recording/@dest attribute '%#x'"), screenSettings.enmDest);
     6022            (*itScreen)->getAttributeValue("maxSizeMB", screenSettings.File.ulMaxSizeMB);
     6023            (*itScreen)->getAttributeValue("horzRes",   screenSettings.Video.ulWidth);
     6024            (*itScreen)->getAttributeValue("vertRes",   screenSettings.Video.ulHeight);
     6025            (*itScreen)->getAttributeValue("rateKbps",  screenSettings.Video.ulRate);
     6026            (*itScreen)->getAttributeValue("fps",       screenSettings.Video.ulFPS);
     6027        }
     6028    }
     6029    else if (   m->sv >= SettingsVersion_v1_14
     6030             && m->sv <  SettingsVersion_v1_19 /* VBox < 7.0 */)
     6031    {
     6032        /* For settings < 1.19 (< VBox 7.0) we only support one recording configuration, that is,
     6033         * all screens have the same configuration. So load/save to/from screen 0. */
     6034        RecordingScreenSettings &screen0 = recording.mapScreens[0];
     6035
     6036        elmRecording.getAttributeValue("maxTime",   screen0.ulMaxTimeS);
     6037        elmRecording.getAttributeValue("options",   screen0.strOptions);
     6038        elmRecording.getAttributeValuePath("file",  screen0.File.strName);
     6039        elmRecording.getAttributeValue("maxSize",   screen0.File.ulMaxSizeMB);
     6040        elmRecording.getAttributeValue("horzRes",   screen0.Video.ulWidth);
     6041        elmRecording.getAttributeValue("vertRes",   screen0.Video.ulHeight);
     6042        elmRecording.getAttributeValue("rate",      screen0.Video.ulRate);
     6043        elmRecording.getAttributeValue("fps",       screen0.Video.ulFPS);
     6044
     6045        /* Convert the enabled screens to the former uint64_t bit array and vice versa. */
     6046        uint64_t cScreens = 0;
     6047        elmRecording.getAttributeValue("screens",   cScreens);
     6048
     6049        /* Propagate the settings from screen 0 to all other screens (= monitors). */
     6050        for (unsigned i = 0; i <  cScreens; i++)
     6051        {
     6052            /* Add screen i to config in any case. */
     6053            recording.mapScreens[i] = screen0;
     6054
     6055            if (cScreens & RT_BIT_64(i)) /* Screen i enabled? */
     6056                recording.mapScreens[i].fEnabled = true;
     6057        }
     6058    }
     6059}
     6060
     6061/**
    59516062 * Called for reading the \<Groups\> element under \<Machine\>.
    59526063 */
     
    60646175            readDVDAndFloppies_pre1_9(*pelmHardware, pSnap->hardware.storage);
    60656176
    6066         const xml::ElementNode *pelmDebugging = elmSnapshot.findChildElement("Debugging");
     6177        const xml::ElementNode *pelmDebugging = elmSnapshot.findChildElement("Debugging"); /** @todo r=andy Shouldn't this be pElement instead of elmSnapshot? Re-visit this! */
    60676178        if (pelmDebugging)
    60686179            readDebugging(*pelmDebugging, pSnap->debugging);
    6069         const xml::ElementNode *pelmAutostart = elmSnapshot.findChildElement("Autostart");
     6180        const xml::ElementNode *pelmAutostart = elmSnapshot.findChildElement("Autostart"); /** @todo r=andy Ditto. */
    60706181        if (pelmAutostart)
    60716182            readAutostart(*pelmAutostart, pSnap->autostart);
     6183        if (m->sv < SettingsVersion_v1_19)
     6184        {
     6185            /* The recording settings were part of the Hardware branch, called "VideoCapture". */
     6186            const xml::ElementNode *pelmVideoCapture = pelmHardware->findChildElement("VideoCapture");
     6187            if (pelmVideoCapture)
     6188                readRecordingSettings(*pelmVideoCapture, pSnap->recordingSettings);
     6189        }
     6190        else /* >= VBox 7.0 */
     6191        {
     6192            const xml::ElementNode *pelmRecording = pElement->findChildElement("Recording");
     6193            if (pelmRecording)
     6194                readRecordingSettings(*pelmRecording, pSnap->recordingSettings);
     6195        }
    60726196        // note: Groups exist only for Machine, not for Snapshot
    60736197
     
    62576381            else if (pelmMachineChild->nameEquals("Autostart"))
    62586382                readAutostart(*pelmMachineChild, autostart);
     6383            else if (pelmMachineChild->nameEquals("Recording"))
     6384                readRecordingSettings(*pelmMachineChild, recordingSettings);
    62596385            else if (pelmMachineChild->nameEquals("Groups"))
    62606386                readGroups(*pelmMachineChild, machineUserData.llGroups);
     
    66836809                pelmDisplay->setAttribute("accelerate2DVideo", hw.graphicsAdapter.fAccelerate2DVideo);
    66846810        }
    6685     }
    6686 
    6687     if (m->sv >= SettingsVersion_v1_14 && !hw.recordingSettings.areDefaultSettings())
    6688     {
    6689         xml::ElementNode *pelmVideoCapture = pelmHardware->createChild("VideoCapture");
    6690 
    6691         if (hw.recordingSettings.fEnabled)
    6692             pelmVideoCapture->setAttribute("enabled", hw.recordingSettings.fEnabled);
    6693 
    6694         /* Right now I don't want to bump the settings version, so just convert the enabled
    6695          * screens to the former uint64t_t bit array and vice versa. */
    6696         uint64_t u64VideoCaptureScreens = 0;
    6697         RecordingScreenMap::const_iterator itScreen = hw.recordingSettings.mapScreens.begin();
    6698         while (itScreen != hw.recordingSettings.mapScreens.end())
    6699         {
    6700             if (itScreen->second.fEnabled)
    6701                u64VideoCaptureScreens |= RT_BIT_64(itScreen->first);
    6702             ++itScreen;
    6703         }
    6704 
    6705         if (u64VideoCaptureScreens)
    6706             pelmVideoCapture->setAttribute("screens",      u64VideoCaptureScreens);
    6707 
    6708         /* At the moment we only support one capturing configuration, that is, all screens
    6709          * have the same configuration. So load/save to/from screen 0. */
    6710         Assert(hw.recordingSettings.mapScreens.size());
    6711         const RecordingScreenMap::const_iterator itScreen0Settings = hw.recordingSettings.mapScreens.find(0);
    6712         Assert(itScreen0Settings != hw.recordingSettings.mapScreens.end());
    6713 
    6714         if (itScreen0Settings->second.ulMaxTimeS)
    6715             pelmVideoCapture->setAttribute("maxTime",      itScreen0Settings->second.ulMaxTimeS);
    6716         if (itScreen0Settings->second.strOptions.isNotEmpty())
    6717             pelmVideoCapture->setAttributePath("options",  itScreen0Settings->second.strOptions);
    6718 
    6719         if (!itScreen0Settings->second.File.strName.isEmpty())
    6720             pelmVideoCapture->setAttributePath("file",     itScreen0Settings->second.File.strName);
    6721         if (itScreen0Settings->second.File.ulMaxSizeMB)
    6722             pelmVideoCapture->setAttribute("maxSize",      itScreen0Settings->second.File.ulMaxSizeMB);
    6723 
    6724         if (   itScreen0Settings->second.Video.ulWidth  != 1024
    6725             || itScreen0Settings->second.Video.ulHeight != 768)
    6726         {
    6727             pelmVideoCapture->setAttribute("horzRes",      itScreen0Settings->second.Video.ulWidth);
    6728             pelmVideoCapture->setAttribute("vertRes",      itScreen0Settings->second.Video.ulHeight);
    6729         }
    6730         if (itScreen0Settings->second.Video.ulRate != 512)
    6731             pelmVideoCapture->setAttribute("rate",         itScreen0Settings->second.Video.ulRate);
    6732         if (itScreen0Settings->second.Video.ulFPS)
    6733             pelmVideoCapture->setAttribute("fps",          itScreen0Settings->second.Video.ulFPS);
    67346811    }
    67356812
     
    79197996}
    79207997
     7998void MachineConfigFile::buildRecordingXML(xml::ElementNode &elmParent, const RecordingSettings &recording)
     7999{
     8000    /* Note: Since settings 1.19 the recording settings have a dedicated XML branch outside of Hardware. */
     8001    if (m->sv >= SettingsVersion_v1_19 /* VBox >= 7.0 */)
     8002    {
     8003        /* Note: elmParent is Machine or Snapshot. */
     8004        xml::ElementNode *pelmRecording = elmParent.createChild("Recording");
     8005
     8006        if (recordingSettings.common.fEnabled)
     8007            pelmRecording->setAttribute("enabled", recording.common.fEnabled);
     8008
     8009        /* Only serialize screens which have non-default settings. */
     8010        size_t cScreensToWrite = 0;
     8011
     8012        RecordingScreenSettingsMap::const_iterator itScreen = recording.mapScreens.begin();
     8013        while (itScreen != recording.mapScreens.end())
     8014        {
     8015            if (!itScreen->second.areDefaultSettings())
     8016                cScreensToWrite++;
     8017            ++itScreen;
     8018        }
     8019
     8020        if (cScreensToWrite)
     8021            pelmRecording->setAttribute("screens", cScreensToWrite);
     8022
     8023        itScreen = recording.mapScreens.begin();
     8024        while (itScreen != recording.mapScreens.end())
     8025        {
     8026            if (!itScreen->second.areDefaultSettings()) /* Skip serializing screen settings which have default settings. */
     8027            {
     8028                xml::ElementNode *pelmScreen = pelmRecording->createChild("Screen");
     8029
     8030                pelmScreen->setAttribute("id",                  itScreen->first); /* The key equals the monitor ID. */
     8031                pelmScreen->setAttribute("enabled",             itScreen->second.fEnabled);
     8032                if (itScreen->second.ulMaxTimeS)
     8033                    pelmScreen->setAttribute("maxTimeS",        itScreen->second.ulMaxTimeS);
     8034                if (itScreen->second.strOptions.isNotEmpty())
     8035                    pelmScreen->setAttributePath("options",     itScreen->second.strOptions);
     8036                pelmScreen->setAttribute("dest",                itScreen->second.enmDest);
     8037                if (!itScreen->second.File.strName.isEmpty())
     8038                    pelmScreen->setAttributePath("file",        itScreen->second.File.strName);
     8039                if (itScreen->second.File.ulMaxSizeMB)
     8040                    pelmScreen->setAttribute("maxSizeMB",       itScreen->second.File.ulMaxSizeMB);
     8041
     8042                if (   itScreen->second.Video.ulWidth  != 1024
     8043                    || itScreen->second.Video.ulHeight != 768)
     8044                {
     8045                    pelmScreen->setAttribute("horzRes",         itScreen->second.Video.ulWidth);
     8046                    pelmScreen->setAttribute("vertRes",         itScreen->second.Video.ulHeight);
     8047                }
     8048                if (itScreen->second.Video.ulRate != 512)
     8049                    pelmScreen->setAttribute("rateKbps",        itScreen->second.Video.ulRate);
     8050                if (itScreen->second.Video.ulFPS)
     8051                    pelmScreen->setAttribute("fps",             itScreen->second.Video.ulFPS);
     8052            }
     8053            ++itScreen;
     8054        }
     8055    }
     8056    else if (   m->sv >= SettingsVersion_v1_14
     8057             && m->sv <  SettingsVersion_v1_19 /* VBox < 7.0 */
     8058             && !recording.areDefaultSettings())
     8059    {
     8060        /* Note: elmParent is Hardware or Snapshot. */
     8061        xml::ElementNode *pelmVideoCapture = elmParent.createChild("VideoCapture");
     8062
     8063        if (recording.common.fEnabled)
     8064            pelmVideoCapture->setAttribute("enabled", recording.common.fEnabled);
     8065
     8066        /* Convert the enabled screens to the former uint64_t bit array and vice versa. */
     8067        uint64_t u64VideoCaptureScreens = 0;
     8068        RecordingScreenSettingsMap::const_iterator itScreen = recording.mapScreens.begin();
     8069        while (itScreen != recording.mapScreens.end())
     8070        {
     8071            if (itScreen->second.fEnabled)
     8072               u64VideoCaptureScreens |= RT_BIT_64(itScreen->first);
     8073            ++itScreen;
     8074        }
     8075
     8076        if (u64VideoCaptureScreens)
     8077            pelmVideoCapture->setAttribute("screens",      u64VideoCaptureScreens);
     8078
     8079        Assert(recording.mapScreens.size());
     8080        const RecordingScreenSettingsMap::const_iterator itScreen0Settings = recording.mapScreens.find(0);
     8081        Assert(itScreen0Settings != recording.mapScreens.end());
     8082
     8083        if (itScreen0Settings->second.ulMaxTimeS)
     8084            pelmVideoCapture->setAttribute("maxTime",      itScreen0Settings->second.ulMaxTimeS);
     8085        if (itScreen0Settings->second.strOptions.isNotEmpty())
     8086            pelmVideoCapture->setAttributePath("options",  itScreen0Settings->second.strOptions);
     8087
     8088        if (!itScreen0Settings->second.File.strName.isEmpty())
     8089            pelmVideoCapture->setAttributePath("file",     itScreen0Settings->second.File.strName);
     8090        if (itScreen0Settings->second.File.ulMaxSizeMB)
     8091            pelmVideoCapture->setAttribute("maxSize",      itScreen0Settings->second.File.ulMaxSizeMB);
     8092
     8093        if (   itScreen0Settings->second.Video.ulWidth  != 1024
     8094            || itScreen0Settings->second.Video.ulHeight != 768)
     8095        {
     8096            pelmVideoCapture->setAttribute("horzRes",      itScreen0Settings->second.Video.ulWidth);
     8097            pelmVideoCapture->setAttribute("vertRes",      itScreen0Settings->second.Video.ulHeight);
     8098        }
     8099        if (itScreen0Settings->second.Video.ulRate != 512)
     8100            pelmVideoCapture->setAttribute("rate",         itScreen0Settings->second.Video.ulRate);
     8101        if (itScreen0Settings->second.Video.ulFPS)
     8102            pelmVideoCapture->setAttribute("fps",          itScreen0Settings->second.Video.ulFPS);
     8103    }
     8104}
     8105
    79218106/**
    79228107 * Creates a \<Groups\> node under elmParent and then writes out the XML
     
    79918176        buildDebuggingXML(*pelmSnapshot, pSnap->debugging);
    79928177        buildAutostartXML(*pelmSnapshot, pSnap->autostart);
     8178        buildRecordingXML(*pelmSnapshot, pSnap->recordingSettings);
    79938179        // note: Groups exist only for Machine, not for Snapshot
    79948180
     
    81578343    buildDebuggingXML(elmMachine, debugging);
    81588344    buildAutostartXML(elmMachine, autostart);
     8345    buildRecordingXML(elmMachine, recordingSettings);
    81598346    buildGroupsXML(elmMachine, machineUserData.llGroups);
    81608347}
     
    83718558            || hardwareMachine.nvramSettings.strKeyId.isNotEmpty()
    83728559            || hardwareMachine.nvramSettings.strKeyStore.isNotEmpty()
     8560            || recordingSettings.areDefaultSettings() == false
    83738561            || strLogKeyId.isNotEmpty()
    83748562            || strLogKeyStore.isEmpty())
     
    86358823            || hardwareMachine.enmLongMode != Hardware::LongMode_Legacy
    86368824            || machineUserData.ovIcon.size() > 0
    8637             || hardwareMachine.recordingSettings.fEnabled)
     8825            || recordingSettings.common.fEnabled)
    86388826        {
    86398827            m->sv = SettingsVersion_v1_14;
Note: See TracChangeset for help on using the changeset viewer.

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