47 q23::expected<QMacScreenCaptureKit::CapturableItems, QString> enumerateResult =
48 QMacScreenCaptureKit::enumerateCapturableItems()
52 return q23::unexpected{ std::move(enumerateResult.error()) };
54 const std::vector<AVFScopedPointer<SCDisplay>> &displays = enumerateResult->displays;
55 auto it = ranges::find_if(
57 [&](
const AVFScopedPointer<SCDisplay> &item) {
58 return item.data().displayID == input;
60 if (it == displays.end())
61 return q23::unexpected(u"Display not found"_s);
64 return AVFScopedPointer<SCDisplay>{ [it->data() retain] };
71 using Error = QPlatformSurfaceCapture::Error;
72 using ErrorDetails = QPlatformSurfaceCapture::ErrorDetails;
74 auto *cocoaScreen = screen.nativeInterface<QNativeInterface::QCocoaScreen>();
76 qCWarning(qLcMacScreenCapture)
77 <<
"Failed to grab QNativeInterface::QCocoaScreen from QScreen";
78 return q23::unexpected{ ErrorDetails{
80 u"Screen capture could not be started."_s } };
83 CGDirectDisplayID cgDisplayId = displayIDForScreen(cocoaScreen->nativeScreen());
85 q23::expected<AVFScopedPointer<SCDisplay>, QString> scDisplayResult = findScDisplay(cgDisplayId);
86 if (!scDisplayResult) {
87 qCWarning(qLcMacScreenCapture)
88 <<
"Could not find associated SCDisplay:"
89 << scDisplayResult.error();
90 return q23::unexpected{ ErrorDetails{
92 u"The selected screen could not be found."_s } };
95 return std::move(*scDisplayResult);
100 const QMacScreenCaptureKit &macScreenCaptureKit)
108 &macScreenCaptureKit,
109 &QMacScreenCaptureKit::newVideoFrameGenerated,
111 [&screenCapture](QMacScreenCaptureKit::StreamId, QVideoFrame videoFrame) {
112 Q_EMIT screenCapture.newVideoFrame(videoFrame);
114 Qt::DirectConnection);
117 &macScreenCaptureKit,
118 &QMacScreenCaptureKit::newVideoFrameGenerated,
120 [&screenCapture](QMacScreenCaptureKit::StreamId streamId, QVideoFrame newFrame) {
121 screenCapture.onNewFrameFormatReceived(streamId, newFrame.surfaceFormat());
123 Qt::QueuedConnection);
126 &macScreenCaptureKit,
127 &QMacScreenCaptureKit::streamStoppedWithError,
129 &QSckScreenCapture::onStreamStoppedWithErrorEvent,
130 Qt::QueuedConnection);
152 using TryStartResult = q23::expected<std::unique_ptr<ActiveData>, ErrorDetails>;
154 auto tryStartStream = [&]() -> TryStartResult {
155 ScreenSource screen = QPlatformSurfaceCapture::source<ScreenSource>();
156 if (!QPlatformSurfaceCapture::checkScreenWithError(screen)) {
157 return q23::unexpected{ ErrorDetails{
158 QPlatformSurfaceCapture::Error::NotFound,
159 u"The selected screen could not be found. It may have been disconnected."_s } };
162 q23::expected<AVFScopedPointer<SCDisplay>, ErrorDetails> scDisplayResult =
163 findScDisplayForScreen(*screen);
164 if (!scDisplayResult)
165 return q23::unexpected{ std::move(scDisplayResult.error()) };
167 QMacScreenCaptureKit::StreamId newStreamId = allocateStreamId();
169 AVFScopedPointer<SCDisplay> &scDisplay = *scDisplayResult;
172 m_session->onSourceActivating(*
this);
175 QMacScreenCaptureKit::CreateStreamInfo createInfo = {};
176 createInfo.streamId = newStreamId;
177 createInfo.connectionSetupFn = [&](QMacScreenCaptureKit &newObject) {
178 setupQMacScreenCaptureKitConnections(*
this, newObject);
180 createInfo.streamSettings.frameRate = frameRate();
181 createInfo.streamSettings.overrideIgnoreCursor = ignoreCursor();
182 using ResultType = q23::expected<std::unique_ptr<QMacScreenCaptureKit>, QString>;
183 std::future<ResultType> streamResultFuture = QMacScreenCaptureKit::createStreamFromDisplay(
186 ResultType streamResult = streamResultFuture.get();
189 m_session->onSourceActivationFailure(*
this);
191 qCWarning(qLcMacScreenCapture)
192 <<
"Failed to start screen capture stream: "
193 << streamResult.error();
194 return q23::unexpected{ ErrorDetails{
195 QPlatformSurfaceCapture::Error::CaptureFailed,
196 u"Screen capture could not be started."_s } };
199 std::unique_ptr<QMacScreenCaptureKit> &macScreenCaptureKit = *streamResult;
201 auto newActiveData = std::make_unique<ActiveData>();
202 newActiveData->macScreenCaptureKit = std::move(macScreenCaptureKit);
203 newActiveData->scDisplay = std::move(scDisplay);
204 newActiveData->streamId = newStreamId;
205 return newActiveData;
209 Q_ASSERT(!m_activeData);
211 TryStartResult result = tryStartStream();
213 const ErrorDetails &error = result.error();
214 QPlatformSurfaceCapture::updateError(error.error, error.description);
218 m_activeData = std::move(*result);
220 m_activeData.reset();
229 Q_ASSERT(m_activeData);
232 QScreen *screen = std::get<ScreenSource>(newSource);
234 screen = QGuiApplication::primaryScreen();
236 return SourceSwitchResult{ q23::unexpected{ ErrorDetails{
238 u"The selected screen could not be found. It may have been disconnected."_s } } };
240 q23::expected<AVFScopedPointer<SCDisplay>, ErrorDetails> scDisplayResult =
241 findScDisplayForScreen(*screen);
242 if (!scDisplayResult)
243 return SourceSwitchResult{ q23::unexpected{ std::move(scDisplayResult.error()) } };
245 std::future<q23::expected<
void, QString>> switchFuture =
246 m_activeData->macScreenCaptureKit->switchToDisplay(scDisplayResult->data());
248 const q23::expected<
void, QString> result = switchFuture.get();
250 qCWarning(qLcMacScreenCapture)
251 <<
"Failed to switch screen capture stream to new screen:"
253 return SourceSwitchResult{ q23::unexpected{ ErrorDetails{
254 Error::CaptureFailed,
255 u"Could not switch capture to the selected screen."_s } } };
258 m_activeData->scDisplay = std::move(*scDisplayResult);
259 return SourceSwitchResult{};
272 QMacScreenCaptureKit::StreamId incomingStreamId,
275 Q_ASSERT(thread()->isCurrentThread());
277 qCDebug(qLcMacScreenCapture)
279 <<
static_cast<int64_t>(incomingStreamId)
280 <<
"stopped with error:"
283 if (activeStreamId() != incomingStreamId)
288 m_activeData.reset();
289 m_videoFrameFormat.reset();
291 QPlatformSurfaceCapture::updateError(
292 Error::CaptureFailed,
293 u"The capture stream was closed by the system"_s);