summary refs log tree commit diff
path: root/src/voip/CallManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/voip/CallManager.cpp')
-rw-r--r--src/voip/CallManager.cpp103
1 files changed, 84 insertions, 19 deletions
diff --git a/src/voip/CallManager.cpp b/src/voip/CallManager.cpp

index ac3ec8ee..58aaa1a4 100644 --- a/src/voip/CallManager.cpp +++ b/src/voip/CallManager.cpp
@@ -34,6 +34,10 @@ #include <xcb/xcb_ewmh.h> #endif +#ifdef Q_OS_WINDOWS +#include <Windows.h> +#endif + #ifdef GSTREAMER_AVAILABLE extern "C" { @@ -82,12 +86,12 @@ CallManager::CallManager(QObject *parent) { #ifdef GSTREAMER_AVAILABLE std::string errorMessage; - if (session_.havePlugins(true, true, ScreenShareType::XDP, &errorMessage)) { - screenShareTypes_.push_back(ScreenShareType::XDP); - screenShareType_ = ScreenShareType::XDP; - } - if (std::getenv("DISPLAY")) { + if (QGuiApplication::platformName() == QStringLiteral("windows") && + session_.havePlugins(true, true, ScreenShareType::D3D11, &errorMessage)) { + screenShareType_ = ScreenShareType::D3D11; + screenShareTypes_.push_back(ScreenShareType::D3D11); + } else if (std::getenv("DISPLAY")) { screenShareTypes_.push_back(ScreenShareType::X11); if (QGuiApplication::platformName() != QStringLiteral("wayland")) { // Selected by default @@ -96,6 +100,12 @@ CallManager::CallManager(QObject *parent) std::swap(screenShareTypes_[0], screenShareTypes_[1]); } } + + if (QGuiApplication::platformName() != QStringLiteral("windows") && + session_.havePlugins(true, true, ScreenShareType::XDP, &errorMessage)) { + screenShareTypes_.push_back(ScreenShareType::XDP); + screenShareType_ = ScreenShareType::XDP; + } #endif connect( @@ -254,7 +264,8 @@ CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int w #ifdef GSTREAMER_AVAILABLE if (callType == CallType::SCREEN) { - if (screenShareType_ == ScreenShareType::X11) { + if (screenShareType_ == ScreenShareType::X11 || + screenShareType_ == ScreenShareType::D3D11) { if (windows_.empty() || windowIndex >= windows_.size()) { nhlog::ui()->error("WebRTC: window index out of range"); return; @@ -270,8 +281,8 @@ CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int w #endif if (haveCallInvite_) { - nhlog::ui()->debug( - "WebRTC: Discarding outbound call for inbound call. localUser is polite party"); + nhlog::ui()->debug("WebRTC: Discarding outbound call for inbound call. " + "localUser is polite party"); if (callParty_ == callee->user_id) { if (callType == callType_) acceptInvite(); @@ -305,7 +316,8 @@ CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int w playRingtone(QUrl(QStringLiteral("qrc:/media/media/ringback.ogg")), true); uint32_t shareWindowId = - callType == CallType::SCREEN && screenShareType_ == ScreenShareType::X11 + callType == CallType::SCREEN && + (screenShareType_ == ScreenShareType::X11 || screenShareType_ == ScreenShareType::D3D11) ? windows_[windowIndex].second : 0; if (!session_.createOffer(callType, screenShareType_, shareWindowId)) { @@ -337,7 +349,7 @@ callHangUpReasonString(CallHangUp::Reason reason) return "User"; } } -} +} // namespace void CallManager::hangUp(CallHangUp::Reason reason) @@ -511,8 +523,8 @@ CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent) void CallManager::acceptInvite() { - // if call was accepted/rejected elsewhere and m.call.select_answer is received - // before acceptInvite + // if call was accepted/rejected elsewhere and m.call.select_answer is + // received before acceptInvite if (!haveCallInvite_) return; @@ -699,7 +711,8 @@ CallManager::handleEvent(const RoomEvent<CallReject> &callRejectEvent) if (callRejectEvent.content.call_id == callid_) { if (session_.state() == webrtc::State::OFFERSENT) { - // only accept reject if webrtc is in OFFERSENT state, else call has been accepted + // only accept reject if webrtc is in OFFERSENT state, else call has been + // accepted emit newMessage( roomid_, CallSelectAnswer{ @@ -861,7 +874,7 @@ bool CallManager::screenShareReady() const { #ifdef GSTREAMER_AVAILABLE - if (screenShareType_ == ScreenShareType::X11) { + if (screenShareType_ == ScreenShareType::X11 || screenShareType_ == ScreenShareType::D3D11) { return true; } else { return ScreenCastPortal::instance().ready(); @@ -875,12 +888,15 @@ QStringList CallManager::screenShareTypeList() { QStringList ret; - ret.reserve(2); + ret.reserve(3); for (ScreenShareType type : screenShareTypes_) { switch (type) { case ScreenShareType::X11: ret.append(tr("X11")); break; + case ScreenShareType::D3D11: + ret.append("DirectX 11"); + break; case ScreenShareType::XDP: ret.append(tr("PipeWire")); break; @@ -893,8 +909,10 @@ CallManager::screenShareTypeList() QStringList CallManager::windowList() { - if (!(std::find(screenShareTypes_.begin(), screenShareTypes_.end(), ScreenShareType::X11) != - screenShareTypes_.end())) { + if (std::find(screenShareTypes_.begin(), screenShareTypes_.end(), ScreenShareType::X11) == + screenShareTypes_.end() && + std::find(screenShareTypes_.begin(), screenShareTypes_.end(), ScreenShareType::D3D11) == + screenShareTypes_.end()) { return {}; } @@ -950,6 +968,32 @@ CallManager::windowList() xcb_ewmh_get_windows_reply_wipe(&clients); } #endif +#ifdef Q_OS_WINDOWS + for (HWND windowHandle = GetTopWindow(nullptr); windowHandle != nullptr; + windowHandle = GetNextWindow(windowHandle, GW_HWNDNEXT)) { + if (!IsWindowVisible(windowHandle)) + continue; + + int titleLength = GetWindowTextLengthW(windowHandle); + if (titleLength == 0) + continue; + + if (GetWindowLong(windowHandle, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) + continue; + + TITLEBARINFO titleInfo; + titleInfo.cbSize = sizeof(titleInfo); + GetTitleBarInfo(windowHandle, &titleInfo); + if (titleInfo.rgstate[0] & STATE_SYSTEM_INVISIBLE) + continue; + + wchar_t *windowTitle = new wchar_t[titleLength + 1]; + GetWindowTextW(windowHandle, windowTitle, titleLength + 1); + + windows_.push_back( + {QString::fromWCharArray(windowTitle), reinterpret_cast<uint64_t>(windowHandle)}); + } +#endif QStringList ret; assert(windows_.size() < std::numeric_limits<int>::max()); ret.reserve(static_cast<int>(windows_.size())); @@ -1007,11 +1051,13 @@ make_preview_sink() { if (QGuiApplication::platformName() == QStringLiteral("wayland")) { return gst_element_factory_make("waylandsink", nullptr); + } else if (QGuiApplication::platformName() == QStringLiteral("windows")) { + return gst_element_factory_make("d3d11videosink", nullptr); } else { return gst_element_factory_make("ximagesink", nullptr); } } -} +} // namespace #endif void @@ -1032,6 +1078,12 @@ CallManager::previewWindow(unsigned int index) const return; } + if (screenShareType_ == ScreenShareType::D3D11 && + (windows_.empty() || index >= windows_.size())) { + nhlog::ui()->error("D3D11 screencast not available"); + return; + } + auto settings = ChatPage::instance()->userSettings(); pipe_ = gst_pipeline_new(nullptr); @@ -1066,6 +1118,19 @@ CallManager::previewWindow(unsigned int index) const gst_bin_add(GST_BIN(pipe_), ximagesrc); screencastsrc = ximagesrc; + } else if (screenShareType_ == ScreenShareType::D3D11) { + GstElement *d3d11screensrc = gst_element_factory_make("d3d11screencapturesrc", nullptr); + if (!d3d11screensrc) { + nhlog::ui()->error("Failed to create d3d11screencapturesrc"); + gst_object_unref(pipe_); + pipe_ = nullptr; + return; + } + g_object_set(d3d11screensrc, "window-handle", windows_[index].second, nullptr); + g_object_set(d3d11screensrc, "show-cursor", !settings->screenShareHideCursor(), nullptr); + + gst_bin_add(GST_BIN(pipe_), d3d11screensrc); + screencastsrc = d3d11screensrc; } else { ScreenCastPortal &sc_portal = ScreenCastPortal::instance(); const ScreenCastPortal::Stream *stream = sc_portal.getStream(); @@ -1171,6 +1236,6 @@ getTurnURIs(const mtx::responses::TurnServer &turnServer) } return ret; } -} +} // namespace #include "moc_CallManager.cpp"