mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Allow choice of single window when sharing screen
This commit is contained in:
parent
70c77cdc44
commit
efe240d609
6 changed files with 131 additions and 24 deletions
|
@ -448,6 +448,7 @@ endif()
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
pkg_check_modules(GSTREAMER IMPORTED_TARGET gstreamer-sdp-1.0>=1.18 gstreamer-webrtc-1.0>=1.18)
|
pkg_check_modules(GSTREAMER IMPORTED_TARGET gstreamer-sdp-1.0>=1.18 gstreamer-webrtc-1.0>=1.18)
|
||||||
if (TARGET PkgConfig::GSTREAMER)
|
if (TARGET PkgConfig::GSTREAMER)
|
||||||
|
pkg_check_modules(XCB IMPORTED_TARGET xcb xcb-ewmh)
|
||||||
add_feature_info(voip ON "GStreamer found. Call support is enabled automatically.")
|
add_feature_info(voip ON "GStreamer found. Call support is enabled automatically.")
|
||||||
else()
|
else()
|
||||||
add_feature_info(voip OFF "GStreamer could not be found on your system. As a consequence call support has been disabled. If you don't want that, make sure gstreamer-sdp-1.0>=1.18 gstreamer-webrtc-1.0>=1.18 can be found via pkgconfig.")
|
add_feature_info(voip OFF "GStreamer could not be found on your system. As a consequence call support has been disabled. If you don't want that, make sure gstreamer-sdp-1.0>=1.18 gstreamer-webrtc-1.0>=1.18 can be found via pkgconfig.")
|
||||||
|
@ -637,6 +638,10 @@ endif()
|
||||||
if (TARGET PkgConfig::GSTREAMER)
|
if (TARGET PkgConfig::GSTREAMER)
|
||||||
target_link_libraries(nheko PRIVATE PkgConfig::GSTREAMER)
|
target_link_libraries(nheko PRIVATE PkgConfig::GSTREAMER)
|
||||||
target_compile_definitions(nheko PRIVATE GSTREAMER_AVAILABLE)
|
target_compile_definitions(nheko PRIVATE GSTREAMER_AVAILABLE)
|
||||||
|
if (TARGET PkgConfig::XCB)
|
||||||
|
target_link_libraries(nheko PRIVATE PkgConfig::XCB)
|
||||||
|
target_compile_definitions(nheko PRIVATE XCB_AVAILABLE)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
|
|
@ -13,9 +13,6 @@ Popup {
|
||||||
anchors.centerIn = parent;
|
anchors.centerIn = parent;
|
||||||
|
|
||||||
frameRateCombo.currentIndex = frameRateCombo.find(Settings.screenShareFrameRate);
|
frameRateCombo.currentIndex = frameRateCombo.find(Settings.screenShareFrameRate);
|
||||||
pipCheckBox.checked = Settings.screenSharePiP;
|
|
||||||
remoteVideoCheckBox.checked = Settings.screenShareRemoteVideo;
|
|
||||||
hideCursorCheckBox.checked = Settings.screenShareHideCursor;
|
|
||||||
}
|
}
|
||||||
palette: colors
|
palette: colors
|
||||||
|
|
||||||
|
@ -33,6 +30,27 @@ Popup {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.rightMargin: 8
|
Layout.rightMargin: 8
|
||||||
|
Layout.bottomMargin: 8
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
text: qsTr("Window:")
|
||||||
|
color: colors.windowText
|
||||||
|
}
|
||||||
|
|
||||||
|
ComboBox {
|
||||||
|
id: windowCombo
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: CallManager.windowList()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.leftMargin: 8
|
||||||
|
Layout.rightMargin: 8
|
||||||
|
Layout.bottomMargin: 8
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
@ -43,7 +61,7 @@ Popup {
|
||||||
ComboBox {
|
ComboBox {
|
||||||
id: frameRateCombo
|
id: frameRateCombo
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.fillWidth: true
|
||||||
model: ["25", "20", "15", "10", "5", "2", "1"]
|
model: ["25", "20", "15", "10", "5", "2", "1"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +70,8 @@ Popup {
|
||||||
CheckBox {
|
CheckBox {
|
||||||
id: pipCheckBox
|
id: pipCheckBox
|
||||||
|
|
||||||
visible: CallManager.cameras.length > 0
|
enabled: CallManager.cameras.length > 0
|
||||||
|
checked: Settings.screenSharePiP
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.rightMargin: 8
|
Layout.rightMargin: 8
|
||||||
|
@ -66,6 +85,7 @@ Popup {
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.rightMargin: 8
|
Layout.rightMargin: 8
|
||||||
text: qsTr("Request remote camera")
|
text: qsTr("Request remote camera")
|
||||||
|
checked: Settings.screenShareRemoteVideo
|
||||||
ToolTip.text: qsTr("View your callee's camera like a regular video call")
|
ToolTip.text: qsTr("View your callee's camera like a regular video call")
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
}
|
}
|
||||||
|
@ -76,7 +96,9 @@ Popup {
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
Layout.leftMargin: 8
|
Layout.leftMargin: 8
|
||||||
Layout.rightMargin: 8
|
Layout.rightMargin: 8
|
||||||
|
Layout.bottomMargin: 8
|
||||||
text: qsTr("Hide mouse cursor")
|
text: qsTr("Hide mouse cursor")
|
||||||
|
checked: Settings.screenShareHideCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
@ -92,11 +114,14 @@ Popup {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (buttonLayout.validateMic()) {
|
if (buttonLayout.validateMic()) {
|
||||||
Settings.microphone = micCombo.currentText;
|
Settings.microphone = micCombo.currentText;
|
||||||
|
if (pipCheckBox.checked)
|
||||||
|
Settings.camera = cameraCombo.currentText;
|
||||||
|
|
||||||
Settings.screenShareFrameRate = frameRateCombo.currentText;
|
Settings.screenShareFrameRate = frameRateCombo.currentText;
|
||||||
Settings.screenSharePiP = pipCheckBox.checked;
|
Settings.screenSharePiP = pipCheckBox.checked;
|
||||||
Settings.screenShareRemoteVideo = remoteVideoCheckBox.checked;
|
Settings.screenShareRemoteVideo = remoteVideoCheckBox.checked;
|
||||||
Settings.screenShareHideCursor = hideCursorCheckBox.checked;
|
Settings.screenShareHideCursor = hideCursorCheckBox.checked;
|
||||||
CallManager.sendInvite(TimelineManager.timeline.roomId(), CallType.SCREEN);
|
CallManager.sendInvite(TimelineManager.timeline.roomId(), CallType.SCREEN, windowCombo.currentIndex);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <QMediaPlaylist>
|
#include <QMediaPlaylist>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
@ -18,6 +19,11 @@
|
||||||
|
|
||||||
#include "mtx/responses/turn_server.hpp"
|
#include "mtx/responses/turn_server.hpp"
|
||||||
|
|
||||||
|
#ifdef XCB_AVAILABLE
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_ewmh.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::vector<mtx::events::msg::CallCandidates::Candidate>)
|
Q_DECLARE_METATYPE(std::vector<mtx::events::msg::CallCandidates::Candidate>)
|
||||||
Q_DECLARE_METATYPE(mtx::events::msg::CallCandidates::Candidate)
|
Q_DECLARE_METATYPE(mtx::events::msg::CallCandidates::Candidate)
|
||||||
Q_DECLARE_METATYPE(mtx::responses::TurnServer)
|
Q_DECLARE_METATYPE(mtx::responses::TurnServer)
|
||||||
|
@ -151,12 +157,18 @@ CallManager::CallManager(QObject *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CallManager::sendInvite(const QString &roomid, CallType callType)
|
CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int windowIndex)
|
||||||
{
|
{
|
||||||
if (isOnCall())
|
if (isOnCall())
|
||||||
return;
|
return;
|
||||||
if (callType == CallType::SCREEN && !screenShareSupported())
|
if (callType == CallType::SCREEN) {
|
||||||
return;
|
if (!screenShareSupported())
|
||||||
|
return;
|
||||||
|
if (windows_.empty() || windowIndex >= windows_.size()) {
|
||||||
|
nhlog::ui()->error("WebRTC: window index out of range");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto roomInfo = cache::singleRoomInfo(roomid.toStdString());
|
auto roomInfo = cache::singleRoomInfo(roomid.toStdString());
|
||||||
if (roomInfo.member_count != 2) {
|
if (roomInfo.member_count != 2) {
|
||||||
|
@ -187,7 +199,7 @@ CallManager::sendInvite(const QString &roomid, CallType callType)
|
||||||
callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url);
|
callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url);
|
||||||
emit newInviteState();
|
emit newInviteState();
|
||||||
playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true);
|
playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true);
|
||||||
if (!session_.createOffer(callType)) {
|
if (!session_.createOffer(callType, windows_[windowIndex].second)) {
|
||||||
emit ChatPage::instance()->showNotification("Problem setting up call.");
|
emit ChatPage::instance()->showNotification("Problem setting up call.");
|
||||||
endCall();
|
endCall();
|
||||||
}
|
}
|
||||||
|
@ -490,6 +502,69 @@ CallManager::stopRingtone()
|
||||||
player_.setPlaylist(nullptr);
|
player_.setPlaylist(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList
|
||||||
|
CallManager::windowList()
|
||||||
|
{
|
||||||
|
windows_.clear();
|
||||||
|
windows_.push_back({"Entire screen", 0});
|
||||||
|
|
||||||
|
#ifdef XCB_AVAILABLE
|
||||||
|
std::unique_ptr<xcb_connection_t, std::function<void(xcb_connection_t *)>> connection(
|
||||||
|
xcb_connect(nullptr, nullptr), [](xcb_connection_t *c) { xcb_disconnect(c); });
|
||||||
|
if (xcb_connection_has_error(connection.get())) {
|
||||||
|
nhlog::ui()->error("Failed to connect to X server");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_ewmh_connection_t ewmh;
|
||||||
|
if (!xcb_ewmh_init_atoms_replies(
|
||||||
|
&ewmh, xcb_ewmh_init_atoms(connection.get(), &ewmh), nullptr)) {
|
||||||
|
nhlog::ui()->error("Failed to connect to EWMH server");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::unique_ptr<xcb_ewmh_connection_t, std::function<void(xcb_ewmh_connection_t *)>>
|
||||||
|
ewmhconnection(&ewmh, [](xcb_ewmh_connection_t *c) { xcb_ewmh_connection_wipe(c); });
|
||||||
|
|
||||||
|
for (int i = 0; i < ewmh.nb_screens; i++) {
|
||||||
|
xcb_ewmh_get_windows_reply_t clients;
|
||||||
|
if (!xcb_ewmh_get_client_list_reply(
|
||||||
|
&ewmh, xcb_ewmh_get_client_list(&ewmh, i), &clients, nullptr)) {
|
||||||
|
nhlog::ui()->error("Failed to request window list");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t w = 0; w < clients.windows_len; w++) {
|
||||||
|
xcb_window_t window = clients.windows[w];
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
xcb_ewmh_get_utf8_strings_reply_t data;
|
||||||
|
auto getName = [](xcb_ewmh_get_utf8_strings_reply_t *r) {
|
||||||
|
std::string name(r->strings, r->strings_len);
|
||||||
|
xcb_ewmh_get_utf8_strings_reply_wipe(r);
|
||||||
|
return name;
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(&ewmh, window);
|
||||||
|
if (xcb_ewmh_get_wm_name_reply(&ewmh, cookie, &data, nullptr))
|
||||||
|
name = getName(&data);
|
||||||
|
|
||||||
|
cookie = xcb_ewmh_get_wm_visible_name(&ewmh, window);
|
||||||
|
if (xcb_ewmh_get_wm_visible_name_reply(&ewmh, cookie, &data, nullptr))
|
||||||
|
name = getName(&data);
|
||||||
|
|
||||||
|
windows_.push_back({QString::fromStdString(name), window});
|
||||||
|
}
|
||||||
|
xcb_ewmh_get_windows_reply_wipe(&clients);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
QStringList ret;
|
||||||
|
ret.reserve(windows_.size());
|
||||||
|
for (const auto &w : windows_)
|
||||||
|
ret.append(w.first);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
getTurnURIs(const mtx::responses::TurnServer &turnServer)
|
getTurnURIs(const mtx::responses::TurnServer &turnServer)
|
||||||
|
|
|
@ -55,13 +55,14 @@ public:
|
||||||
static bool screenShareSupported();
|
static bool screenShareSupported();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void sendInvite(const QString &roomid, webrtc::CallType);
|
void sendInvite(const QString &roomid, webrtc::CallType, unsigned int windowIndex = 0);
|
||||||
void syncEvent(const mtx::events::collections::TimelineEvents &event);
|
void syncEvent(const mtx::events::collections::TimelineEvents &event);
|
||||||
void toggleMicMute();
|
void toggleMicMute();
|
||||||
void toggleLocalPiP() { session_.toggleLocalPiP(); }
|
void toggleLocalPiP() { session_.toggleLocalPiP(); }
|
||||||
void acceptInvite();
|
void acceptInvite();
|
||||||
void hangUp(
|
void hangUp(
|
||||||
mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
|
mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
|
||||||
|
QStringList windowList();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
|
void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
|
||||||
|
@ -91,6 +92,7 @@ private:
|
||||||
std::vector<std::string> turnURIs_;
|
std::vector<std::string> turnURIs_;
|
||||||
QTimer turnServerTimer_;
|
QTimer turnServerTimer_;
|
||||||
QMediaPlayer player_;
|
QMediaPlayer player_;
|
||||||
|
std::vector<std::pair<QString, uint32_t>> windows_;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool handleEvent_(const mtx::events::collections::TimelineEvents &event);
|
bool handleEvent_(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
|
@ -362,7 +362,7 @@ getResolution(GstElement *pipe, const gchar *elementName, const gchar *padName)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int>
|
std::pair<int, int>
|
||||||
getPiPDimensions(const std::pair<int, int> resolution, int fullWidth, double scaleFactor)
|
getPiPDimensions(const std::pair<int, int> &resolution, int fullWidth, double scaleFactor)
|
||||||
{
|
{
|
||||||
int pipWidth = fullWidth * scaleFactor;
|
int pipWidth = fullWidth * scaleFactor;
|
||||||
int pipHeight = static_cast<double>(resolution.second) / resolution.first * pipWidth;
|
int pipHeight = static_cast<double>(resolution.second) / resolution.first * pipWidth;
|
||||||
|
@ -629,11 +629,12 @@ WebRTCSession::havePlugins(bool isVideo, std::string *errorMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebRTCSession::createOffer(CallType callType)
|
WebRTCSession::createOffer(CallType callType, uint32_t shareWindowId)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
isOffering_ = true;
|
isOffering_ = true;
|
||||||
callType_ = callType;
|
callType_ = callType;
|
||||||
|
shareWindowId_ = shareWindowId;
|
||||||
|
|
||||||
// opus and vp8 rtp payload types must be defined dynamically
|
// opus and vp8 rtp payload types must be defined dynamically
|
||||||
// therefore from the range [96-127]
|
// therefore from the range [96-127]
|
||||||
|
@ -888,15 +889,12 @@ WebRTCSession::addVideoPipeline(int vp8PayloadType)
|
||||||
if (callType_ == CallType::VIDEO && !devices_.haveCamera())
|
if (callType_ == CallType::VIDEO && !devices_.haveCamera())
|
||||||
return !isOffering_;
|
return !isOffering_;
|
||||||
|
|
||||||
auto settings = ChatPage::instance()->userSettings();
|
auto settings = ChatPage::instance()->userSettings();
|
||||||
if (callType_ == CallType::SCREEN && settings->screenSharePiP() && !devices_.haveCamera())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GstElement *camerafilter = nullptr;
|
GstElement *camerafilter = nullptr;
|
||||||
GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
|
GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
|
||||||
GstElement *tee = gst_element_factory_make("tee", "videosrctee");
|
GstElement *tee = gst_element_factory_make("tee", "videosrctee");
|
||||||
gst_bin_add_many(GST_BIN(pipe_), videoconvert, tee, nullptr);
|
gst_bin_add_many(GST_BIN(pipe_), videoconvert, tee, nullptr);
|
||||||
if (callType_ == CallType::VIDEO || settings->screenSharePiP()) {
|
if (callType_ == CallType::VIDEO || (settings->screenSharePiP() && devices_.haveCamera())) {
|
||||||
std::pair<int, int> resolution;
|
std::pair<int, int> resolution;
|
||||||
std::pair<int, int> frameRate;
|
std::pair<int, int> frameRate;
|
||||||
GstDevice *device = devices_.videoDevice(resolution, frameRate);
|
GstDevice *device = devices_.videoDevice(resolution, frameRate);
|
||||||
|
@ -947,7 +945,7 @@ WebRTCSession::addVideoPipeline(int vp8PayloadType)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
|
g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
|
||||||
g_object_set(ximagesrc, "xid", 0, nullptr);
|
g_object_set(ximagesrc, "xid", shareWindowId_, nullptr);
|
||||||
g_object_set(
|
g_object_set(
|
||||||
ximagesrc, "show-pointer", !settings->screenShareHideCursor(), nullptr);
|
ximagesrc, "show-pointer", !settings->screenShareHideCursor(), nullptr);
|
||||||
|
|
||||||
|
@ -962,7 +960,7 @@ WebRTCSession::addVideoPipeline(int vp8PayloadType)
|
||||||
gst_caps_unref(caps);
|
gst_caps_unref(caps);
|
||||||
gst_bin_add_many(GST_BIN(pipe_), ximagesrc, capsfilter, nullptr);
|
gst_bin_add_many(GST_BIN(pipe_), ximagesrc, capsfilter, nullptr);
|
||||||
|
|
||||||
if (settings->screenSharePiP()) {
|
if (settings->screenSharePiP() && devices_.haveCamera()) {
|
||||||
GstElement *compositor = gst_element_factory_make("compositor", nullptr);
|
GstElement *compositor = gst_element_factory_make("compositor", nullptr);
|
||||||
g_object_set(compositor, "background", 1, nullptr);
|
g_object_set(compositor, "background", 1, nullptr);
|
||||||
gst_bin_add(GST_BIN(pipe_), compositor);
|
gst_bin_add(GST_BIN(pipe_), compositor);
|
||||||
|
@ -1101,6 +1099,7 @@ WebRTCSession::clear()
|
||||||
pipe_ = nullptr;
|
pipe_ = nullptr;
|
||||||
webrtc_ = nullptr;
|
webrtc_ = nullptr;
|
||||||
busWatchId_ = 0;
|
busWatchId_ = 0;
|
||||||
|
shareWindowId_ = 0;
|
||||||
haveAudioStream_ = false;
|
haveAudioStream_ = false;
|
||||||
haveVideoStream_ = false;
|
haveVideoStream_ = false;
|
||||||
localPiPSinkPad_ = nullptr;
|
localPiPSinkPad_ = nullptr;
|
||||||
|
@ -1143,7 +1142,7 @@ WebRTCSession::haveLocalPiP() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebRTCSession::createOffer(webrtc::CallType) { return false; }
|
bool WebRTCSession::createOffer(webrtc::CallType, uint32_t) { return false; }
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebRTCSession::acceptOffer(const std::string &)
|
WebRTCSession::acceptOffer(const std::string &)
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
bool isRemoteVideoRecvOnly() const { return isRemoteVideoRecvOnly_; }
|
bool isRemoteVideoRecvOnly() const { return isRemoteVideoRecvOnly_; }
|
||||||
bool isRemoteVideoSendOnly() const { return isRemoteVideoSendOnly_; }
|
bool isRemoteVideoSendOnly() const { return isRemoteVideoSendOnly_; }
|
||||||
|
|
||||||
bool createOffer(webrtc::CallType);
|
bool createOffer(webrtc::CallType, uint32_t shareWindowId);
|
||||||
bool acceptOffer(const std::string &sdp);
|
bool acceptOffer(const std::string &sdp);
|
||||||
bool acceptAnswer(const std::string &sdp);
|
bool acceptAnswer(const std::string &sdp);
|
||||||
void acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
|
void acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
|
||||||
|
@ -100,6 +100,7 @@ private:
|
||||||
GstElement *webrtc_ = nullptr;
|
GstElement *webrtc_ = nullptr;
|
||||||
unsigned int busWatchId_ = 0;
|
unsigned int busWatchId_ = 0;
|
||||||
std::vector<std::string> turnServers_;
|
std::vector<std::string> turnServers_;
|
||||||
|
uint32_t shareWindowId_ = 0;
|
||||||
|
|
||||||
bool init(std::string *errorMessage = nullptr);
|
bool init(std::string *errorMessage = nullptr);
|
||||||
bool startPipeline(int opusPayloadType, int vp8PayloadType);
|
bool startPipeline(int opusPayloadType, int vp8PayloadType);
|
||||||
|
|
Loading…
Reference in a new issue