Revision control

++ // Copyright (C) 2023 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 "qwindowcapture.h"
++
++ #include <QtMultimedia/qmediacapturesession.h>
++ #include <QtMultimedia/private/qplatformmediaintegration_p.h>
++ #include <QtMultimedia/private/qplatformsurfacecapture_p.h>
++ #include <QtMultimedia/private/qwindowcapture_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ static QWindowCapture::Error toWindowCaptureError(QPlatformSurfaceCapture::Error error)
++ {
++ return static_cast<QWindowCapture::Error>(error);
++ }
++
++ /*!
++ \class QWindowCapture
++ \inmodule QtMultimedia
++ \ingroup multimedia
++ \ingroup multimedia_video
++ \since 6.6
++
++ \brief This class is used for capturing a window.
++
++ The class captures a window. It is managed by
++ the \l QMediaCaptureSession class where the captured window can be displayed
++ in a video preview object or recorded to a file.
++
++ The following snippet shows how to select one of the capturable windows and
++ display the result in a \l QVideoWidget:
++
++ \snippet multimedia-snippets/windowcapturesnippets.cpp Basic setup
++
++ \include qwindowcapture-limitations.qdocinc {content} {Q}
++
++ \sa QMediaCaptureSession, QCapturableWindow
++ */
++ /*!
++ \qmltype WindowCapture
++ \nativetype QWindowCapture
++ \inqmlmodule QtMultimedia
++ \ingroup multimedia_qml
++ \ingroup multimedia_video_qml
++ \since 6.6
++
++ \brief This type is used for capturing a window.
++
++ WindowCapture captures a window. It is managed by
++ \l {QtMultimedia::CaptureSession}{CaptureSession} where the
++ captured window can be displayed in a video preview object or
++ recorded to a file.
++
++ The code below shows a simple capture session that captures one of the
++ available windows with WindowCapture and plays it back in a
++ \l {QtMultimedia::VideoOutput}{VideoOutput}.
++
++ \snippet multimedia-snippets/windowcapturesnippets.qml Basic setup
++
++ \include qwindowcapture-limitations.qdocinc {content} {}
++
++ \sa CaptureSession, CapturableWindow
++ */
++
++ /*!
++ \enum QWindowCapture::Error
++
++ Enumerates error codes that can be signaled by the QWindowCapture class.
++ errorString() provides detailed information about the error cause.
++
++ \value NoError No error
++ \value InternalError Internal window capturing driver error
++ \value CapturingNotSupported Window capturing is not supported
++ \value CaptureFailed Capturing window failed
++ \value NotFound Selected window not found
++ */
++
++ /*!
++ Constructs a new QWindowCapture object with \a parent.
++ */
++ QWindowCapture::QWindowCapture(QObject *parent) : QObject(*new QWindowCapturePrivate, parent)
++ {
++ Q_D(QWindowCapture);
++
++ qRegisterMetaType<QCapturableWindow>();
++
++ auto platformCapture = QPlatformMediaIntegration::instance()->createWindowCapture(this);
++
++ if (platformCapture) {
++ connect(platformCapture, &QPlatformSurfaceCapture::activeChanged, this,
++ &QWindowCapture::activeChanged);
++ connect(platformCapture, &QPlatformSurfaceCapture::errorChanged, this,
++ &QWindowCapture::errorChanged);
++ connect(platformCapture, &QPlatformSurfaceCapture::errorOccurred, this,
++ [this](QPlatformSurfaceCapture::Error error, const QString &errorString) {
++ Q_EMIT errorOccurred(toWindowCaptureError(error), errorString);
++ });
++ connect(platformCapture,
++ qOverload<QCapturableWindow>(&QPlatformSurfaceCapture::sourceChanged), this,
++ &QWindowCapture::windowChanged);
++
++ connect(platformCapture, &QPlatformSurfaceCapture::frameRateChanged, this,
++ &QWindowCapture::maximumFrameRateChanged);
++
++ d->platformWindowCapture.reset(platformCapture);
++ }
++ }
++
++ /*!
++ Destroys the object.
++ */
++ QWindowCapture::~QWindowCapture()
++ {
++ Q_D(QWindowCapture);
++
++ d->platformWindowCapture.reset();
++
++ if (d->captureSession)
++ d->captureSession->setWindowCapture(nullptr);
++ }
++
++ /*!
++ \qmlmethod list<CapturableWindow> QtMultimedia::WindowCapture::capturableWindows()
++
++ Returns a list of \l{QtMultimedia::CapturableWindow}{CapturableWindow}
++ objects that are currently available for capturing.
++
++ \note On macOS, invoking this method will trigger the "Screen Recording" permission
++ dialog. If permissions have not yet been granted, this method will return an empty list.
++ Invoking it multiple times will bring this dialog to the foreground.
++ */
++ /*!
++ \fn QList<QCapturableWindow> QWindowCapture::capturableWindows()
++
++ Returns a list of \l QCapturableWindow objects that are currently
++ available for capturing.
++
++ \note On macOS, invoking this method will trigger the "Screen Recording" permission
++ dialog. If permissions have not yet been granted, this method will return an empty list.
++ Invoking it multiple times will bring this dialog to the foreground.
++ */
++ QList<QCapturableWindow> QWindowCapture::capturableWindows()
++ {
++ return QPlatformMediaIntegration::instance()->capturableWindowsList();
++ }
++
++ /*!
++ Returns the capture session this QWindowCapture is connected to.
++
++ Use \l QMediaCaptureSession::setWindowCapture() to connect the window capture
++ to a session.
++ */
++ QMediaCaptureSession *QWindowCapture::captureSession() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->captureSession;
++ }
++
++ /*!
++ \qmlproperty Window QtMultimedia::WindowCapture::window
++ Describes the window for capturing.
++
++ Setting this property to an invalid window on an active
++ WindowCapture will cause it to go inactive and emit
++ an error.
++
++ \sa capturableWindows
++ */
++
++ /*!
++ \property QWindowCapture::window
++ \brief the window for capturing.
++
++ Setting this property to an invalid window on an active
++ QWindowCapture will cause it to go inactive and emit
++ an error.
++
++ \sa QWindowCapture::capturableWindows
++ */
++ QCapturableWindow QWindowCapture::window() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture ? d->platformWindowCapture->source<QCapturableWindow>()
++ : QCapturableWindow();
++ }
++
++ void QWindowCapture::setWindow(QCapturableWindow window)
++ {
++ Q_D(QWindowCapture);
++
++ if (d->platformWindowCapture)
++ d->platformWindowCapture->setSource(window);
++ }
++
++ /*!
++ \qmlproperty bool QtMultimedia::WindowCapture::active
++ Describes whether the capturing is currently active.
++
++ \sa start(), stop()
++ */
++
++ /*!
++ \property QWindowCapture::active
++ \brief whether the capturing is currently active.
++
++ \sa start(), stop()
++ */
++ bool QWindowCapture::isActive() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture && d->platformWindowCapture->isActive();
++ }
++
++ void QWindowCapture::setActive(bool active)
++ {
++ Q_D(QWindowCapture);
++
++ if (d->platformWindowCapture)
++ d->platformWindowCapture->setActive(active);
++ }
++
++ /*!
++ \since 6.12
++ \property QWindowCapture::maximumFrameRate
++ \brief The window 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 window 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 QWindowCapture
++ goes active.
++ */
++ void QWindowCapture::setMaximumFrameRate(std::optional<qreal> frameRate)
++ {
++ Q_D(QWindowCapture);
++
++ if (d->platformWindowCapture)
++ d->platformWindowCapture->setFrameRate(frameRate);
++ }
++
++ std::optional<qreal> QWindowCapture::maximumFrameRate() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture ? d->platformWindowCapture->frameRate() : std::nullopt;
++ }
++
++ /*!
++ \qmlmethod void QtMultimedia::WindowCapture::start()
++
++ Starts capturing the \l window.
++
++ This is equivalent to setting the \l active property to \c true.
++ */
++
++ /*!
++ \fn void QWindowCapture::start()
++
++ Starts capturing the \l window.
++
++ This is equivalent to setting the \l active property to true.
++ */
++
++ /*!
++ \qmlmethod void QtMultimedia::WindowCapture::stop()
++
++ Stops capturing.
++
++ This is equivalent to setting the \l active property to \c false.
++ */
++
++ /*!
++ \fn void QWindowCapture::stop()
++
++ Stops capturing.
++
++ This is equivalent to setting the \l active property to false.
++ */
++
++ /*!
++ \qmlsignal QtMultimedia::WindowCapture::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 QWindowCapture::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::WindowCapture::error
++ Returns a code of the last error.
++
++ \qmlenumeratorsfrom QWindowCapture::Error
++ */
++
++ /*!
++ \property QWindowCapture::error
++ \brief the code of the last error.
++ */
++ QWindowCapture::Error QWindowCapture::error() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture ? toWindowCaptureError(d->platformWindowCapture->error())
++ : CapturingNotSupported;
++ }
++
++ /*!
++ \qmlsignal QtMultimedia::WindowCapture::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::WindowCapture::error}{error} for what values may
++ be passed.
++
++ \sa {QtMultimedia::WindowCapture::error}{error}
++ */
++ /*!
++ \fn void QWindowCapture::errorOccurred(QWindowCapture::Error error, const QString &errorString)
++
++ Signals when an \a error occurs, along with the \a errorString.
++ */
++ /*!
++ \qmlproperty string QtMultimedia::WindowCapture::errorString
++ Returns a human readable string describing the cause of error.
++ */
++
++ /*!
++ \property QWindowCapture::errorString
++ \brief a human readable string describing the cause of error.
++ */
++ QString QWindowCapture::errorString() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture
++ ? d->platformWindowCapture->errorString()
++ : QLatin1StringView("Capturing is not supported on this platform");
++ }
++
++ void QWindowCapture::setCaptureSession(QMediaCaptureSession *captureSession)
++ {
++ Q_D(QWindowCapture);
++
++ d->captureSession = captureSession;
++ }
++
++ QPlatformSurfaceCapture *QWindowCapture::platformWindowCapture() const
++ {
++ Q_D(const QWindowCapture);
++
++ return d->platformWindowCapture.get();
++ }
++
++ void QWindowCapturePrivate::setIgnoreCursor(bool ignore)
++ {
++ if (!platformWindowCapture)
++ return;
++ platformWindowCapture->setIgnoreCursor(ignore);
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qwindowcapture.cpp"