VirtualBox

Changeset 105266 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Jul 11, 2024 7:49:37 AM (6 months ago)
Author:
vboxsync
Message:

Recording: Implemented support for a dedicated progress object, which is exposed to API clients. This can be used for better tracking the recording progress as well as for error reporting. The RecordingSettings API also now has a dedicated start() method to start recording, as well as support for attaching to an already ongoing recording by retrieving the progress object at a later time. Adapted FE/Qt (draft, see @todos), FE/VBoxManage and the Validation Kit testdriver to the new APIs. VBoxManage also can attach to an ongoing recording now. The recording progress object also will have multiple operations to get the recording progress for convenience. bugref:10718

Location:
trunk/src/VBox/Main/src-server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r105087 r105266  
    1420814208
    1420914209/**
     14210 * @note Caller needs to take the machine's lock if needed.
     14211 */
     14212HRESULT SessionMachine::i_onRecordingStateChange(BOOL aEnable, IProgress **aProgress)
     14213{
     14214    LogFlowThisFunc(("\n"));
     14215
     14216    AutoCaller autoCaller(this);
     14217    AssertComRCReturn(autoCaller.hrc(), autoCaller.hrc());
     14218
     14219    ComPtr<IInternalSessionControl> directControl;
     14220    {
     14221        if (mData->mSession.mLockType == LockType_VM)
     14222            directControl = mData->mSession.mDirectControl;
     14223    }
     14224
     14225    /* ignore notifications sent after #OnSessionEnd() is called */
     14226    if (!directControl)
     14227        return S_OK;
     14228
     14229    return directControl->OnRecordingStateChange(aEnable, aProgress);
     14230}
     14231
     14232/**
    1421014233 * @note Locks this object for reading.
    1421114234 */
    14212 HRESULT SessionMachine::i_onRecordingChange(BOOL aEnable)
     14235HRESULT SessionMachine::i_onRecordingScreenStateChange(BOOL aEnable, ULONG aScreen)
    1421314236{
    1421414237    LogFlowThisFunc(("\n"));
     
    1422814251        return S_OK;
    1422914252
    14230     return directControl->OnRecordingChange(aEnable);
     14253    return directControl->OnRecordingScreenStateChange(aEnable, aScreen);
    1423114254}
    1423214255
  • trunk/src/VBox/Main/src-server/RecordingSettingsImpl.cpp

    r98292 r105266  
    5656    const ComObjPtr<RecordingSettings>      pPeer;
    5757    RecordingScreenSettingsObjMap           mapScreenObj;
     58    /** The recording progress object.
     59     *  There only is one recording progress per VM, shared between multiple recording settings (if any). */
     60    ComPtr<IProgress>                       mProgress;
    5861
    5962    // use the XML settings structure in the members for simplicity
     
    98101
    99102    i_applyDefaults();
     103
     104    /* Note: The progress object gets created in i_start(). */
    100105
    101106    autoInitSpan.setSucceeded();
     
    145150
    146151    m->mapScreenObj = aThat->m->mapScreenObj;
     152    m->mProgress = aThat->m->mProgress;
    147153
    148154    autoInitSpan.setSucceeded();
     
    199205    }
    200206
     207    m->mProgress = aThat->m->mProgress;
     208
    201209    if (SUCCEEDED(hrc))
    202210        autoInitSpan.setSucceeded();
     
    219227        return;
    220228
    221     /* Make sure to destroy screen objects attached to this object.
    222      * Note: This also decrements the refcount of a screens object, in case it's shared among other recording settings. */
    223     i_destroyAllScreenObj(m->mapScreenObj);
     229    i_reset();
    224230
    225231    m->bd.free();
     
    264270
    265271        alock.release();
    266 
    267         hrc = m->pMachine->i_onRecordingChange(enable);
    268         if (FAILED(hrc))
    269         {
    270             com::ErrorInfo errMachine; /* Get error info from machine call above. */
    271 
    272             /*
    273              * Normally we would do the actual change _after_ i_onRecordingChange() succeeded.
    274              * We cannot do this because that function uses RecordSettings::GetEnabled to
    275              * determine if it should start or stop capturing. Therefore we need to manually
    276              * undo change.
    277              */
    278             alock.acquire();
    279             m->bd->fEnabled = m->bd.backedUpData()->fEnabled;
    280 
    281             if (errMachine.isBasicAvailable())
    282                 hrc = setError(errMachine);
    283         }
    284         else
    285         {
    286             AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);  // pMachine is const, needs no locking
    287             m->pMachine->i_setModified(Machine::IsModified_Recording);
    288 
    289             /* Make sure to release the mutable dependency lock from above before
    290              * actually saving the settings. */
    291             adep.release();
    292 
    293             /** Save settings if online - @todo why is this required? -- @bugref{6818} */
    294             if (Global::IsOnline(m->pMachine->i_getMachineState()))
    295             {
    296                 com::ErrorInfo errMachine;
    297                 hrc = m->pMachine->i_saveSettings(NULL, mlock);
    298                 if (FAILED(hrc))
    299                 {
    300                     /* Got error info from machine call above. */
    301                     if (errMachine.isBasicAvailable())
    302                         hrc = setError(errMachine);
    303                 }
    304             }
    305         }
    306272    }
    307273
     
    354320}
    355321
     322HRESULT RecordingSettings::getProgress(ComPtr<IProgress> &aProgress)
     323{
     324#ifndef VBOX_WITH_RECORDING
     325    ReturnComNotImplemented();
     326#else
     327    /* the machine needs to be mutable */
     328    AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
     329    if (FAILED(adep.hrc())) return adep.hrc();
     330
     331    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     332
     333    if (m->mProgress.isNull())
     334        return setError(E_FAIL, tr("Recording not started"));
     335
     336    return m->mProgress.queryInterfaceTo(aProgress.asOutParam());
     337#endif
     338}
     339
    356340HRESULT RecordingSettings::getScreenSettings(ULONG uScreenId, ComPtr<IRecordingScreenSettings> &aRecordScreenSettings)
    357341{
     
    380364
    381365    return VBOX_E_OBJECT_NOT_FOUND;
     366}
     367
     368HRESULT RecordingSettings::start(ComPtr<IProgress> &aProgress)
     369{
     370#ifndef VBOX_WITH_RECORDING
     371    ReturnComNotImplemented();
     372#else
     373    /* the machine needs to be mutable */
     374    AutoMutableOrSavedOrRunningStateDependency adep(m->pMachine);
     375    if (FAILED(adep.hrc())) return adep.hrc();
     376
     377    /* Recording not explicitly enabled before? Do so now. */
     378    if (!m->bd->fEnabled)
     379    {
     380        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     381
     382        m->bd.backup();
     383        m->bd->fEnabled = true;
     384
     385        alock.release();
     386
     387        /* Note: m->bd->fEnabled is transient here, i.e. we don't save the settings,
     388                 as this would otherwise start the recording on VM startup the next time. */
     389    }
     390
     391    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     392
     393    if (m->mProgress.isNotNull())
     394    {
     395        BOOL fCompleted = FALSE;
     396        HRESULT const hrc = m->mProgress->COMGETTER(Completed)(&fCompleted);
     397        ComAssertComRCRetRC(hrc);
     398        if (!fCompleted)
     399            return setError(E_FAIL, tr("Recording already started"));
     400    }
     401
     402    m->mProgress.setNull(); /* Make sure to release a dangling object from a former run. */
     403
     404    alock.release();
     405
     406    int const vrc = i_start();
     407    if (RT_FAILURE(vrc))
     408    {
     409        /* Make the progress' error info available to the caller on failure. */
     410        ComObjPtr<IVirtualBoxErrorInfo> pErrorInfo;
     411        m->mProgress->COMGETTER(ErrorInfo)(pErrorInfo.asOutParam());
     412        return setError(pErrorInfo);
     413    }
     414
     415    return m->mProgress.queryInterfaceTo(aProgress.asOutParam());
     416#endif
    382417}
    383418
     
    553588    LogFlowThisFuncEnter();
    554589
     590    i_stop();
     591
     592    /* Make sure to destroy screen objects attached to this object.
     593     * Note: This also decrements the refcount of a screens object, in case it's shared among other recording settings. */
    555594    i_destroyAllScreenObj(m->mapScreenObj);
    556595}
     
    824863
    825864/**
     865 * Starts recording.
     866 *
     867 * @returns VBox status code.
     868 */
     869int RecordingSettings::i_start(void)
     870{
     871    AssertReturn(m->mProgress.isNull(), VERR_WRONG_ORDER);
     872
     873    HRESULT hrc = m->pMachine->i_onRecordingStateChange(TRUE /* Enable recording */, m->mProgress.asOutParam());
     874    if (FAILED(hrc))
     875        return VERR_RECORDING_INIT_FAILED;
     876
     877    return VINF_SUCCESS;
     878}
     879
     880/**
     881 * Stops recording. Does nothing if recording already has been stopped.
     882 *
     883 * @returns VBox status code.
     884 */
     885int RecordingSettings::i_stop(void)
     886{
     887    if (m->mProgress.isNull()) /* Not started? */
     888        return VINF_SUCCESS;
     889
     890    /* Note: Returned progress object is just a dummy / not needed for disabling recording. */
     891    HRESULT hrc = m->pMachine->i_onRecordingStateChange(FALSE /* Disable recording */, m->mProgress.asOutParam());
     892    if (SUCCEEDED(hrc))
     893        m->mProgress.setNull();
     894
     895    if (FAILED(hrc))
     896        return VERR_COM_UNEXPECTED;
     897
     898    return VINF_SUCCESS;
     899}
     900
     901/**
    826902 * Synchronizes the screen settings (COM) objects and configuration data
    827903 * to the number of the machine's configured displays.
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