| 1 | // Copyright (C) 2022 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #include "qscreencapture.h" | 
| 5 | #include "qmediacapturesession.h" | 
| 6 | #include <private/qplatformmediaintegration_p.h> | 
| 7 | #include <private/qplatformsurfacecapture_p.h> | 
| 8 | #include <private/qobject_p.h> | 
| 9 |  | 
| 10 | QT_BEGIN_NAMESPACE | 
| 11 |  | 
| 12 | static QScreenCapture::Error toScreenCaptureError(QPlatformSurfaceCapture::Error error) | 
| 13 | { | 
| 14 |     return static_cast<QScreenCapture::Error>(error); | 
| 15 | } | 
| 16 |  | 
| 17 | class QScreenCapturePrivate : public QObjectPrivate | 
| 18 | { | 
| 19 | public: | 
| 20 |     QMediaCaptureSession *captureSession = nullptr; | 
| 21 |     std::unique_ptr<QPlatformSurfaceCapture> platformScreenCapture; | 
| 22 | }; | 
| 23 |  | 
| 24 | /*! | 
| 25 |     \class QScreenCapture | 
| 26 |     \inmodule QtMultimedia | 
| 27 |     \ingroup multimedia | 
| 28 |     \ingroup multimedia_video | 
| 29 |     \since 6.5 | 
| 30 |  | 
| 31 |     \brief This class is used for capturing a screen. | 
| 32 |  | 
| 33 |     The class captures a screen. It is managed by | 
| 34 |     the QMediaCaptureSession class where the captured screen can be displayed | 
| 35 |     in a video preview object or recorded to a file. | 
| 36 |  | 
| 37 |     \snippet multimedia-snippets/media.cpp Media recorder | 
| 38 |  | 
| 39 |     \include qscreencapture-limitations.qdocinc {content} {Q} | 
| 40 |  | 
| 41 |     \sa QWindowCapture, QMediaCaptureSession | 
| 42 | */ | 
| 43 | /*! | 
| 44 |     \qmltype ScreenCapture | 
| 45 |     \nativetype QScreenCapture | 
| 46 |     \brief This type is used for capturing a screen. | 
| 47 |  | 
| 48 |     \inqmlmodule QtMultimedia | 
| 49 |     \ingroup multimedia_qml | 
| 50 |     \ingroup multimedia_video_qml | 
| 51 |  | 
| 52 |     ScreenCapture captures a screen. It is managed by | 
| 53 |     MediaCaptureSession where the captured screen can be displayed | 
| 54 |     in a video preview object or recorded to a file. | 
| 55 |  | 
| 56 |     \since 6.5 | 
| 57 |     The code below shows a simple capture session with ScreenCapture playing | 
| 58 |     back the captured primary screen view in VideoOutput. | 
| 59 |  | 
| 60 | \qml | 
| 61 |     CaptureSession { | 
| 62 |         id: captureSession | 
| 63 |         screenCapture: ScreenCapture { | 
| 64 |             id: screenCapture | 
| 65 |             active: true | 
| 66 |         } | 
| 67 |         videoOutput: VideoOutput { | 
| 68 |             id: videoOutput | 
| 69 |         } | 
| 70 |     } | 
| 71 | \endqml | 
| 72 |  | 
| 73 |     \include qscreencapture-limitations.qdocinc {content} {} | 
| 74 |  | 
| 75 |     \sa WindowCapture, CaptureSession | 
| 76 | */ | 
| 77 |  | 
| 78 | QScreenCapture::QScreenCapture(QObject *parent) | 
| 79 |     : QObject(*new QScreenCapturePrivate, parent) | 
| 80 | { | 
| 81 |     Q_D(QScreenCapture); | 
| 82 |  | 
| 83 |     auto platformCapture = QPlatformMediaIntegration::instance()->createScreenCapture(this); | 
| 84 |     if (platformCapture) { | 
| 85 |         connect(sender: platformCapture, signal: &QPlatformSurfaceCapture::activeChanged, context: this, | 
| 86 |                 slot: &QScreenCapture::activeChanged); | 
| 87 |         connect(sender: platformCapture, signal: &QPlatformSurfaceCapture::errorChanged, context: this, | 
| 88 |                 slot: &QScreenCapture::errorChanged); | 
| 89 |         connect(sender: platformCapture, signal: &QPlatformSurfaceCapture::errorOccurred, context: this, | 
| 90 |                 slot: [this](QPlatformSurfaceCapture::Error error, QString errorString) { | 
| 91 |                     emit errorOccurred(error: toScreenCaptureError(error), errorString); | 
| 92 |                 }); | 
| 93 |  | 
| 94 |         connect(sender: platformCapture, | 
| 95 |                 signal: qOverload<QPlatformSurfaceCapture::ScreenSource>( | 
| 96 |                         &QPlatformSurfaceCapture::sourceChanged), | 
| 97 |                 context: this, slot: &QScreenCapture::screenChanged); | 
| 98 |  | 
| 99 |         d->platformScreenCapture.reset(p: platformCapture); | 
| 100 |     } | 
| 101 | } | 
| 102 |  | 
| 103 | QScreenCapture::~QScreenCapture() | 
| 104 | { | 
| 105 |     Q_D(QScreenCapture); | 
| 106 |  | 
| 107 |     // Reset platformScreenCapture in the destructor to avoid having broken ref in the object. | 
| 108 |     d->platformScreenCapture.reset(); | 
| 109 |  | 
| 110 |     if (d->captureSession) | 
| 111 |         d->captureSession->setScreenCapture(nullptr); | 
| 112 | } | 
| 113 |  | 
| 114 | /*! | 
| 115 |     \enum QScreenCapture::Error | 
| 116 |  | 
| 117 |     Enumerates error codes that can be signaled by the QScreenCapture class. | 
| 118 |     errorString() provides detailed information about the error cause. | 
| 119 |  | 
| 120 |     \value NoError                      No error | 
| 121 |     \value InternalError                Internal screen capturing driver error | 
| 122 |     \value CapturingNotSupported        Capturing is not supported | 
| 123 |     \value CaptureFailed                Capturing screen failed | 
| 124 |     \value NotFound                     Selected screen not found | 
| 125 | */ | 
| 126 |  | 
| 127 | /*! | 
| 128 |     Returns the capture session this QScreenCapture is connected to. | 
| 129 |  | 
| 130 |     Use QMediaCaptureSession::setScreenCapture() to connect the camera to | 
| 131 |     a session. | 
| 132 | */ | 
| 133 | QMediaCaptureSession *QScreenCapture::captureSession() const | 
| 134 | { | 
| 135 |     Q_D(const QScreenCapture); | 
| 136 |  | 
| 137 |     return d->captureSession; | 
| 138 | } | 
| 139 |  | 
| 140 | /*! | 
| 141 |     \qmlproperty bool QtMultimedia::ScreenCapture::active | 
| 142 |     Describes whether the capturing is currently active. | 
| 143 | */ | 
| 144 |  | 
| 145 | /*! | 
| 146 |     \property QScreenCapture::active | 
| 147 |     \brief whether the capturing is currently active. | 
| 148 | */ | 
| 149 | void QScreenCapture::setActive(bool active) | 
| 150 | { | 
| 151 |     Q_D(QScreenCapture); | 
| 152 |  | 
| 153 |     if (d->platformScreenCapture) | 
| 154 |         d->platformScreenCapture->setActive(active); | 
| 155 | } | 
| 156 |  | 
| 157 | bool QScreenCapture::isActive() const | 
| 158 | { | 
| 159 |     Q_D(const QScreenCapture); | 
| 160 |  | 
| 161 |     return d->platformScreenCapture && d->platformScreenCapture->isActive(); | 
| 162 | } | 
| 163 |  | 
| 164 | /*! | 
| 165 |     \qmlproperty Screen QtMultimedia::ScreenCapture::screen | 
| 166 |     Describes the screen for capturing. | 
| 167 | */ | 
| 168 |  | 
| 169 | /*! | 
| 170 |     \property QScreenCapture::screen | 
| 171 |     \brief the screen for capturing. | 
| 172 | */ | 
| 173 |  | 
| 174 | void QScreenCapture::setScreen(QScreen *screen) | 
| 175 | { | 
| 176 |     Q_D(QScreenCapture); | 
| 177 |  | 
| 178 |     if (d->platformScreenCapture) | 
| 179 |         d->platformScreenCapture->setSource(QPlatformSurfaceCapture::ScreenSource(screen)); | 
| 180 | } | 
| 181 |  | 
| 182 | QScreen *QScreenCapture::screen() const | 
| 183 | { | 
| 184 |     Q_D(const QScreenCapture); | 
| 185 |  | 
| 186 |     return d->platformScreenCapture | 
| 187 |             ? d->platformScreenCapture->source<QPlatformSurfaceCapture::ScreenSource>() | 
| 188 |             : nullptr; | 
| 189 | } | 
| 190 |  | 
| 191 | /*! | 
| 192 |     \qmlproperty enumeration QtMultimedia::ScreenCapture::error | 
| 193 |     Returns a code of the last error. | 
| 194 | */ | 
| 195 |  | 
| 196 | /*! | 
| 197 |     \property QScreenCapture::error | 
| 198 |     \brief the code of the last error. | 
| 199 | */ | 
| 200 | QScreenCapture::Error QScreenCapture::error() const | 
| 201 | { | 
| 202 |     Q_D(const QScreenCapture); | 
| 203 |  | 
| 204 |     return d->platformScreenCapture ? toScreenCaptureError(error: d->platformScreenCapture->error()) | 
| 205 |                                     : CapturingNotSupported; | 
| 206 | } | 
| 207 |  | 
| 208 | /*! | 
| 209 |     \fn void QScreenCapture::errorOccurred(QScreenCapture::Error error, const QString &errorString) | 
| 210 |  | 
| 211 |     Signals when an \a error occurs, along with the \a errorString. | 
| 212 | */ | 
| 213 | /*! | 
| 214 |     \qmlproperty string QtMultimedia::ScreenCapture::errorString | 
| 215 |     Returns a human readable string describing the cause of error. | 
| 216 | */ | 
| 217 |  | 
| 218 | /*! | 
| 219 |     \property QScreenCapture::errorString | 
| 220 |     \brief a human readable string describing the cause of error. | 
| 221 | */ | 
| 222 | QString QScreenCapture::errorString() const | 
| 223 | { | 
| 224 |     Q_D(const QScreenCapture); | 
| 225 |  | 
| 226 |     return d->platformScreenCapture ? d->platformScreenCapture->errorString() | 
| 227 |                                     : QLatin1StringView("Capturing is not support on this platform" ); | 
| 228 | } | 
| 229 | /*! | 
| 230 |     \fn void QScreenCapture::start() | 
| 231 |  | 
| 232 |     Starts screen capture. | 
| 233 | */ | 
| 234 | /*! | 
| 235 |     \fn void QScreenCapture::stop() | 
| 236 |  | 
| 237 |     Stops screen capture. | 
| 238 | */ | 
| 239 | /*! | 
| 240 |     \internal | 
| 241 | */ | 
| 242 | void QScreenCapture::setCaptureSession(QMediaCaptureSession *captureSession) | 
| 243 | { | 
| 244 |     Q_D(QScreenCapture); | 
| 245 |  | 
| 246 |     d->captureSession = captureSession; | 
| 247 | } | 
| 248 |  | 
| 249 | /*! | 
| 250 |     \internal | 
| 251 | */ | 
| 252 | class QPlatformSurfaceCapture *QScreenCapture::platformScreenCapture() const | 
| 253 | { | 
| 254 |     Q_D(const QScreenCapture); | 
| 255 |  | 
| 256 |     return d->platformScreenCapture.get(); | 
| 257 | } | 
| 258 |  | 
| 259 | QT_END_NAMESPACE | 
| 260 |  | 
| 261 | #include "moc_qscreencapture.cpp" | 
| 262 |  |