Revision control
++ // Copyright (C) 2022 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++
++ #include "qscreencapture.h"
++
++ #include <QtMultimedia/qmediacapturesession.h>
++ #include <QtMultimedia/private/qplatformmediaintegration_p.h>
++ #include <QtMultimedia/private/qplatformsurfacecapture_p.h>
++ #include <QtMultimedia/private/qscreencapture_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ static QScreenCapture::Error toScreenCaptureError(QPlatformSurfaceCapture::Error error)
++ {
++ return static_cast<QScreenCapture::Error>(error);
++ }
++
++ /*!
++ \class QScreenCapture
++ \inmodule QtMultimedia
++ \ingroup multimedia
++ \ingroup multimedia_video
++ \since 6.5
++
++ \brief This class is used for capturing a screen.
++
++ The class captures a screen. It is managed by
++ the \l QMediaCaptureSession class where the captured screen can be displayed
++ in a video preview object or recorded to a file.
++
++ The following snippet shows how to capture the primary screen and display
++ the result in a QVideoWidget:
++
++ \snippet multimedia-snippets/screencapturesnippets.cpp Basic setup
++
++ \include qscreencapture-limitations.qdocinc {content} {Q}
++
++ \sa QWindowCapture, QMediaCaptureSession
++ */
++ /*!
++ \qmltype ScreenCapture
++ \nativetype QScreenCapture
++ \brief This type is used for capturing a screen.
++
++ \inqmlmodule QtMultimedia
++ \ingroup multimedia_qml
++ \ingroup multimedia_video_qml
++ \since 6.5
++
++ ScreenCapture captures a screen. It is managed by
++ \l{QtMultimedia::CaptureSession}{CaptureSession} where the captured
++ screen can be displayed in a video preview object or recorded to a
++ file.
++
++ The code below shows a simple capture session with ScreenCapture playing
++ back the captured primary screen view in \l {QtMultimedia::VideoOutput}{VideoOutput}.
++
++ \snippet multimedia-snippets/screencapturesnippets.qml Basic setup
++
++ \include qscreencapture-limitations.qdocinc {content} {}
++
++ \sa WindowCapture, CaptureSession
++ */
++
++ QScreenCapture::QScreenCapture(QObject *parent)
++ : QObject(*new QScreenCapturePrivate, parent)
++ {
++ Q_D(QScreenCapture);
++
++ auto platformCapture = QPlatformMediaIntegration::instance()->createScreenCapture(this);
++ if (platformCapture) {
++ connect(platformCapture, &QPlatformSurfaceCapture::activeChanged, this,
++ &QScreenCapture::activeChanged);
++ connect(platformCapture, &QPlatformSurfaceCapture::errorChanged, this,
++ &QScreenCapture::errorChanged);
++ connect(platformCapture, &QPlatformSurfaceCapture::errorOccurred, this,
++ [this](QPlatformSurfaceCapture::Error error, const QString &errorString) {
++ Q_EMIT errorOccurred(toScreenCaptureError(error), errorString);
++ });
++
++ connect(platformCapture,
++ qOverload<QPlatformSurfaceCapture::ScreenSource>(
++ &QPlatformSurfaceCapture::sourceChanged),
++ this, &QScreenCapture::screenChanged);
++
++ connect(platformCapture, &QPlatformSurfaceCapture::frameRateChanged, this,
++ &QScreenCapture::maximumFrameRateChanged);
++
++ d->platformScreenCapture.reset(platformCapture);
++ }
++ }
++
++ QScreenCapture::~QScreenCapture()
++ {
++ Q_D(QScreenCapture);
++
++ // Reset platformScreenCapture in the destructor to avoid having broken ref in the object.
++ d->platformScreenCapture.reset();
++
++ if (d->captureSession)
++ d->captureSession->setScreenCapture(nullptr);
++ }
++
++ /*!
++ \enum QScreenCapture::Error
++
++ Enumerates error codes that can be signaled by the QScreenCapture class.
++ errorString() provides detailed information about the error cause.
++
++ \value NoError No error
++ \value InternalError Internal screen capturing driver error
++ \value CapturingNotSupported Capturing is not supported
++ \value CaptureFailed Capturing screen failed
++ \value NotFound Selected screen not found
++ */
++
++ /*!
++ Returns the capture session this QScreenCapture is connected to.
++
++ Use QMediaCaptureSession::setScreenCapture() to connect the screen capture
++ to a session.
++ */
++ QMediaCaptureSession *QScreenCapture::captureSession() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->captureSession;
++ }
++
++ /*!
++ \qmlproperty bool QtMultimedia::ScreenCapture::active
++ Describes whether the capturing is currently active.
++
++ \sa start(), stop()
++ */
++
++ /*!
++ \property QScreenCapture::active
++ \brief whether the capturing is currently active.
++
++ \sa start(), stop()
++ */
++ void QScreenCapture::setActive(bool active)
++ {
++ Q_D(QScreenCapture);
++
++ if (d->platformScreenCapture)
++ d->platformScreenCapture->setActive(active);
++ }
++
++ bool QScreenCapture::isActive() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture && d->platformScreenCapture->isActive();
++ }
++
++ /*!
++ \qmlproperty Screen QtMultimedia::ScreenCapture::screen
++ Describes the screen for capturing.
++
++ If null \c Screen is set, the primary screen will be selected
++ when the \c ScreenCapture instance gets activated.
++
++ \sa {QtQuick::Application::screens}{Application.screens}
++ */
++
++ /*!
++ \property QScreenCapture::screen
++ \brief the screen for capturing.
++
++ If null \l QScreen is set, \l QGuiApplication::primaryScreen will be selected
++ when the \c QScreenCapture instance gets activated.
++
++ \sa QGuiApplication::screens(), QGuiApplication::primaryScreen()
++ */
++
++ void QScreenCapture::setScreen(QScreen *screen)
++ {
++ Q_D(QScreenCapture);
++
++ if (d->platformScreenCapture)
++ d->platformScreenCapture->setSource(QPlatformSurfaceCapture::ScreenSource(screen));
++ }
++
++ QScreen *QScreenCapture::screen() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture
++ ? d->platformScreenCapture->source<QPlatformSurfaceCapture::ScreenSource>()
++ : nullptr;
++ }
++
++ /*!
++ \qmlsignal QtMultimedia::ScreenCapture::errorChanged()
++
++ This signal is emitted when the \l{error} or \l{errorString} properties are changed.
++
++ This signal is not emitted whenever multiple identical errors are raised. To track such
++ errors, use the signal \l errorOccurred.
++ */
++
++ /*!
++ \fn void QScreenCapture::errorChanged()
++
++ This signal is emitted when the \l{error} or \l{errorString} properties are changed.
++
++ This signal is not emitted whenever multiple identical errors are raised. To track such
++ errors, use the signal \l errorOccurred.
++ */
++
++ /*!
++ \qmlproperty enumeration QtMultimedia::ScreenCapture::error
++ Returns a code of the last error.
++
++ \qmlenumeratorsfrom QScreenCapture::Error
++ */
++
++ /*!
++ \property QScreenCapture::error
++ \brief the code of the last error.
++ */
++ QScreenCapture::Error QScreenCapture::error() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture ? toScreenCaptureError(d->platformScreenCapture->error())
++ : CapturingNotSupported;
++ }
++
++ /*!
++ \qmlsignal QtMultimedia::ScreenCapture::errorOccurred(int error, string errorString)
++
++ Signals when an \a error occurs, along with the \a errorString.
++
++ For the error parameter, see the enumeration table in
++ \l {QtMultimedia::ScreenCapture::error}{error} for what values may
++ be passed.
++
++ \sa {QtMultimedia::ScreenCapture::error}{error}
++ */
++ /*!
++ \fn void QScreenCapture::errorOccurred(QScreenCapture::Error error, const QString &errorString)
++
++ Signals when an \a error occurs, along with the \a errorString.
++ */
++ /*!
++ \qmlproperty string QtMultimedia::ScreenCapture::errorString
++ Returns a human readable string describing the cause of error.
++ */
++
++ /*!
++ \property QScreenCapture::errorString
++ \brief a human readable string describing the cause of error.
++ */
++ QString QScreenCapture::errorString() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture ? d->platformScreenCapture->errorString()
++ : QLatin1StringView("Capturing is not supported on this platform");
++ }
++
++ /*!
++ \since 6.12
++ \property QScreenCapture::maximumFrameRate
++ \brief The screen capture frame rate upper limit.
++
++ This can be set to override the capture frame rate used by default based on
++ e.g. display refresh rate, but only as an upper limit since screen capture
++ produces frames at a variable rate. Setting this higher than the display
++ refresh rate is not recommended and can cause errors.
++
++ Any changes to this property are applied the next time the QScreenCapture
++ goes active.
++ */
++ void QScreenCapture::setMaximumFrameRate(std::optional<qreal> frameRate)
++ {
++ Q_D(QScreenCapture);
++
++ if (d->platformScreenCapture)
++ d->platformScreenCapture->setFrameRate(frameRate);
++ }
++
++ std::optional<qreal> QScreenCapture::maximumFrameRate() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture ? d->platformScreenCapture->frameRate() : std::nullopt;
++ }
++
++ /*!
++ \qmlmethod void QtMultimedia::ScreenCapture::start()
++
++ Starts capturing the \l screen.
++
++ This is equivalent to setting the \l active property to \c true.
++ */
++
++ /*!
++ \fn void QScreenCapture::start()
++
++ Starts capturing the \l screen.
++
++ This is equivalent to setting the \l active property to true.
++ */
++
++ /*!
++ \qmlmethod void QtMultimedia::ScreenCapture::stop()
++
++ Stops capturing.
++
++ This is equivalent to setting the \l active property to \c false.
++ */
++
++ /*!
++ \fn void QScreenCapture::stop()
++
++ Stops capturing.
++
++ This is equivalent to setting the \l active property to false.
++ */
++ /*!
++ \internal
++ */
++ void QScreenCapture::setCaptureSession(QMediaCaptureSession *captureSession)
++ {
++ Q_D(QScreenCapture);
++
++ d->captureSession = captureSession;
++ }
++
++ /*!
++ \internal
++ */
++ class QPlatformSurfaceCapture *QScreenCapture::platformScreenCapture() const
++ {
++ Q_D(const QScreenCapture);
++
++ return d->platformScreenCapture.get();
++ }
++
++ void QScreenCapturePrivate::setIgnoreCursor(bool ignore)
++ {
++ if (!platformScreenCapture)
++ return;
++ platformScreenCapture->setIgnoreCursor(ignore);
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qscreencapture.cpp"