From d1f3a3ef40a69fe50efe6e2b76400e7f5f5dfb6c Mon Sep 17 00:00:00 2001 From: trilene Date: Tue, 27 Oct 2020 13:14:06 -0400 Subject: Support video calls --- src/dialogs/AcceptCall.cpp | 66 ++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 25 deletions(-) (limited to 'src/dialogs/AcceptCall.cpp') diff --git a/src/dialogs/AcceptCall.cpp b/src/dialogs/AcceptCall.cpp index 2b47b7dc..8323e9ff 100644 --- a/src/dialogs/AcceptCall.cpp +++ b/src/dialogs/AcceptCall.cpp @@ -19,23 +19,32 @@ AcceptCall::AcceptCall(const QString &caller, const QString &roomName, const QString &avatarUrl, QSharedPointer settings, + bool isVideo, QWidget *parent) : QWidget(parent) { std::string errorMessage; - if (!WebRTCSession::instance().init(&errorMessage)) { + WebRTCSession *session = &WebRTCSession::instance(); + if (!session->havePlugins(false, &errorMessage)) { emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); emit close(); return; } - audioDevices_ = WebRTCSession::instance().getAudioSourceNames( - settings->defaultAudioSource().toStdString()); - if (audioDevices_.empty()) { + if (isVideo && !session->havePlugins(true, &errorMessage)) { + emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); + emit close(); + return; + } + session->refreshDevices(); + microphones_ = session->getDeviceNames(false, settings->microphone().toStdString()); + if (microphones_.empty()) { emit ChatPage::instance()->showNotification( - "Incoming call: No audio sources found."); + tr("Incoming call: No microphone found.")); emit close(); return; } + if (isVideo) + cameras_ = session->getDeviceNames(true, settings->camera().toStdString()); setAutoFillBackground(true); setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); @@ -77,9 +86,10 @@ AcceptCall::AcceptCall(const QString &caller, const int iconSize = 22; QLabel *callTypeIndicator = new QLabel(this); callTypeIndicator->setPixmap( - QIcon(":/icons/icons/ui/place-call.png").pixmap(QSize(iconSize * 2, iconSize * 2))); + QIcon(isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png") + .pixmap(QSize(iconSize * 2, iconSize * 2))); - QLabel *callTypeLabel = new QLabel("Voice Call", this); + QLabel *callTypeLabel = new QLabel(isVideo ? tr("Video Call") : tr("Voice Call"), this); labelFont.setPointSizeF(f.pointSizeF() * 1.1); callTypeLabel->setFont(labelFont); callTypeLabel->setAlignment(Qt::AlignCenter); @@ -88,7 +98,8 @@ AcceptCall::AcceptCall(const QString &caller, buttonLayout->setSpacing(18); acceptBtn_ = new QPushButton(tr("Accept"), this); acceptBtn_->setDefault(true); - acceptBtn_->setIcon(QIcon(":/icons/icons/ui/place-call.png")); + acceptBtn_->setIcon( + QIcon(isVideo ? ":/icons/icons/ui/video-call.png" : ":/icons/icons/ui/place-call.png")); acceptBtn_->setIconSize(QSize(iconSize, iconSize)); rejectBtn_ = new QPushButton(tr("Reject"), this); @@ -97,18 +108,17 @@ AcceptCall::AcceptCall(const QString &caller, buttonLayout->addWidget(acceptBtn_); buttonLayout->addWidget(rejectBtn_); - auto deviceLayout = new QHBoxLayout; - auto audioLabel = new QLabel(this); - audioLabel->setPixmap( - QIcon(":/icons/icons/ui/microphone-unmute.png").pixmap(QSize(iconSize, iconSize))); + microphoneCombo_ = new QComboBox(this); + for (const auto &m : microphones_) + microphoneCombo_->addItem(QIcon(":/icons/icons/ui/microphone-unmute.png"), + QString::fromStdString(m)); - auto deviceList = new QComboBox(this); - for (const auto &d : audioDevices_) - deviceList->addItem(QString::fromStdString(d)); - - deviceLayout->addStretch(); - deviceLayout->addWidget(audioLabel); - deviceLayout->addWidget(deviceList); + if (!cameras_.empty()) { + cameraCombo_ = new QComboBox(this); + for (const auto &c : cameras_) + cameraCombo_->addItem(QIcon(":/icons/icons/ui/video-call.png"), + QString::fromStdString(c)); + } if (displayNameLabel) layout->addWidget(displayNameLabel, 0, Qt::AlignCenter); @@ -117,12 +127,17 @@ AcceptCall::AcceptCall(const QString &caller, layout->addWidget(callTypeIndicator, 0, Qt::AlignCenter); layout->addWidget(callTypeLabel, 0, Qt::AlignCenter); layout->addLayout(buttonLayout); - layout->addLayout(deviceLayout); - - connect(acceptBtn_, &QPushButton::clicked, this, [this, deviceList, settings]() { - WebRTCSession::instance().setAudioSource(deviceList->currentIndex()); - settings->setDefaultAudioSource( - QString::fromStdString(audioDevices_[deviceList->currentIndex()])); + layout->addWidget(microphoneCombo_); + if (cameraCombo_) + layout->addWidget(cameraCombo_); + + connect(acceptBtn_, &QPushButton::clicked, this, [this, settings, session]() { + settings->setMicrophone( + QString::fromStdString(microphones_[microphoneCombo_->currentIndex()])); + if (cameraCombo_) { + settings->setCamera( + QString::fromStdString(cameras_[cameraCombo_->currentIndex()])); + } emit accept(); emit close(); }); @@ -131,4 +146,5 @@ AcceptCall::AcceptCall(const QString &caller, emit close(); }); } + } -- cgit 1.5.1 From b1300aff46625cce33f0244a173e09cba985dc3a Mon Sep 17 00:00:00 2001 From: trilene Date: Tue, 27 Oct 2020 17:26:46 -0400 Subject: Fix crash on exit --- src/CallManager.cpp | 7 +------ src/CallManager.h | 5 +---- src/ChatPage.cpp | 1 - src/WebRTCSession.cpp | 34 ++++++++++++++++++++-------------- src/WebRTCSession.h | 4 ---- src/dialogs/AcceptCall.cpp | 14 ++++++++------ src/dialogs/AcceptCall.h | 3 --- 7 files changed, 30 insertions(+), 38 deletions(-) (limited to 'src/dialogs/AcceptCall.cpp') diff --git a/src/CallManager.cpp b/src/CallManager.cpp index 4cd98a9f..a376a607 100644 --- a/src/CallManager.cpp +++ b/src/CallManager.cpp @@ -12,7 +12,6 @@ #include "Logging.h" #include "MainWindow.h" #include "MatrixClient.h" -#include "UserSettingsPage.h" #include "WebRTCSession.h" #include "dialogs/AcceptCall.h" @@ -30,18 +29,15 @@ std::vector getTurnURIs(const mtx::responses::TurnServer &turnServer); } -CallManager::CallManager(QSharedPointer userSettings) +CallManager::CallManager() : QObject() , session_(WebRTCSession::instance()) , turnServerTimer_(this) - , settings_(userSettings) { qRegisterMetaType>(); qRegisterMetaType(); qRegisterMetaType(); - session_.setSettings(userSettings); - connect( &session_, &WebRTCSession::offerCreated, @@ -265,7 +261,6 @@ CallManager::handleEvent(const RoomEvent &callInviteEvent) caller.display_name, QString::fromStdString(roomInfo.name), QString::fromStdString(roomInfo.avatar_url), - settings_, isVideo, MainWindow::instance()); connect(dialog, &dialogs::AcceptCall::accept, this, [this, callInviteEvent, isVideo]() { diff --git a/src/CallManager.h b/src/CallManager.h index c3afa155..f0e46b4b 100644 --- a/src/CallManager.h +++ b/src/CallManager.h @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -16,7 +15,6 @@ namespace mtx::responses { struct TurnServer; } -class UserSettings; class WebRTCSession; class CallManager : public QObject @@ -24,7 +22,7 @@ class CallManager : public QObject Q_OBJECT public: - CallManager(QSharedPointer); + CallManager(); void sendInvite(const QString &roomid, bool isVideo); void hangUp( @@ -59,7 +57,6 @@ private: std::vector remoteICECandidates_; std::vector turnURIs_; QTimer turnServerTimer_; - QSharedPointer settings_; QMediaPlayer player_; template diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index c86c6128..4d46b8c6 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -69,7 +69,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) , isConnected_(true) , userSettings_{userSettings} , notificationsManager(this) - , callManager_(userSettings) { setObjectName("chatPage"); diff --git a/src/WebRTCSession.cpp b/src/WebRTCSession.cpp index 177bdf7a..40a9753e 100644 --- a/src/WebRTCSession.cpp +++ b/src/WebRTCSession.cpp @@ -9,6 +9,7 @@ #include #include +#include "ChatPage.h" #include "Logging.h" #include "UserSettingsPage.h" #include "WebRTCSession.h" @@ -847,7 +848,7 @@ WebRTCSession::startPipeline(int opusPayloadType, int vp8PayloadType) webrtc_ = gst_bin_get_by_name(GST_BIN(pipe_), "webrtcbin"); - if (settings_->useStunServer()) { + if (ChatPage::instance()->userSettings()->useStunServer()) { nhlog::ui()->info("WebRTC: setting STUN server: {}", STUN_SERVER); g_object_set(webrtc_, "stun-server", STUN_SERVER, nullptr); } @@ -902,15 +903,17 @@ WebRTCSession::startPipeline(int opusPayloadType, int vp8PayloadType) bool WebRTCSession::createPipeline(int opusPayloadType, int vp8PayloadType) { - auto it = std::find_if(audioSources_.cbegin(), audioSources_.cend(), [this](const auto &s) { - return s.name == settings_->microphone().toStdString(); - }); + std::string microphoneSetting = + ChatPage::instance()->userSettings()->microphone().toStdString(); + auto it = + std::find_if(audioSources_.cbegin(), + audioSources_.cend(), + [µphoneSetting](const auto &s) { return s.name == microphoneSetting; }); if (it == audioSources_.cend()) { - nhlog::ui()->error("WebRTC: unknown microphone: {}", - settings_->microphone().toStdString()); + nhlog::ui()->error("WebRTC: unknown microphone: {}", microphoneSetting); return false; } - nhlog::ui()->debug("WebRTC: microphone: {}", it->name); + nhlog::ui()->debug("WebRTC: microphone: {}", microphoneSetting); GstElement *source = gst_device_create_element(it->device, nullptr); GstElement *volume = gst_element_factory_make("volume", "srclevel"); @@ -977,21 +980,24 @@ WebRTCSession::addVideoPipeline(int vp8PayloadType) if (videoSources_.empty()) return !isOffering_; - auto it = std::find_if(videoSources_.cbegin(), videoSources_.cend(), [this](const auto &s) { - return s.name == settings_->camera().toStdString(); - }); + std::string cameraSetting = ChatPage::instance()->userSettings()->camera().toStdString(); + auto it = std::find_if(videoSources_.cbegin(), + videoSources_.cend(), + [&cameraSetting](const auto &s) { return s.name == cameraSetting; }); if (it == videoSources_.cend()) { - nhlog::ui()->error("WebRTC: unknown camera: {}", settings_->camera().toStdString()); + nhlog::ui()->error("WebRTC: unknown camera: {}", cameraSetting); return false; } - std::string resSetting = settings_->cameraResolution().toStdString(); + std::string resSetting = + ChatPage::instance()->userSettings()->cameraResolution().toStdString(); const std::string &res = resSetting.empty() ? it->caps.front().resolution : resSetting; - std::string frSetting = settings_->cameraFrameRate().toStdString(); + std::string frSetting = + ChatPage::instance()->userSettings()->cameraFrameRate().toStdString(); const std::string &fr = frSetting.empty() ? it->caps.front().frameRates.front() : frSetting; auto resolution = tokenise(res, 'x'); auto frameRate = tokenise(fr, '/'); - nhlog::ui()->debug("WebRTC: camera: {}", it->name); + nhlog::ui()->debug("WebRTC: camera: {}", cameraSetting); nhlog::ui()->debug("WebRTC: camera resolution: {}x{}", resolution.first, resolution.second); nhlog::ui()->debug("WebRTC: camera frame rate: {}/{}", frameRate.first, frameRate.second); diff --git a/src/WebRTCSession.h b/src/WebRTCSession.h index d5e195a8..9c7778e7 100644 --- a/src/WebRTCSession.h +++ b/src/WebRTCSession.h @@ -4,13 +4,11 @@ #include #include -#include #include "mtx/events/voip.hpp" typedef struct _GstElement GstElement; class QQuickItem; -class UserSettings; namespace webrtc { Q_NAMESPACE @@ -57,7 +55,6 @@ public: bool toggleMicMute(); void end(); - void setSettings(QSharedPointer settings) { settings_ = settings; } void setTurnServers(const std::vector &uris) { turnServers_ = uris; } void refreshDevices(); @@ -95,7 +92,6 @@ private: GstElement *pipe_ = nullptr; GstElement *webrtc_ = nullptr; unsigned int busWatchId_ = 0; - QSharedPointer settings_; std::vector turnServers_; bool init(std::string *errorMessage = nullptr); diff --git a/src/dialogs/AcceptCall.cpp b/src/dialogs/AcceptCall.cpp index 8323e9ff..3d25ad82 100644 --- a/src/dialogs/AcceptCall.cpp +++ b/src/dialogs/AcceptCall.cpp @@ -18,7 +18,6 @@ AcceptCall::AcceptCall(const QString &caller, const QString &displayName, const QString &roomName, const QString &avatarUrl, - QSharedPointer settings, bool isVideo, QWidget *parent) : QWidget(parent) @@ -35,8 +34,10 @@ AcceptCall::AcceptCall(const QString &caller, emit close(); return; } + session->refreshDevices(); - microphones_ = session->getDeviceNames(false, settings->microphone().toStdString()); + microphones_ = session->getDeviceNames( + false, ChatPage::instance()->userSettings()->microphone().toStdString()); if (microphones_.empty()) { emit ChatPage::instance()->showNotification( tr("Incoming call: No microphone found.")); @@ -44,7 +45,8 @@ AcceptCall::AcceptCall(const QString &caller, return; } if (isVideo) - cameras_ = session->getDeviceNames(true, settings->camera().toStdString()); + cameras_ = session->getDeviceNames( + true, ChatPage::instance()->userSettings()->camera().toStdString()); setAutoFillBackground(true); setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); @@ -131,11 +133,11 @@ AcceptCall::AcceptCall(const QString &caller, if (cameraCombo_) layout->addWidget(cameraCombo_); - connect(acceptBtn_, &QPushButton::clicked, this, [this, settings, session]() { - settings->setMicrophone( + connect(acceptBtn_, &QPushButton::clicked, this, [this]() { + ChatPage::instance()->userSettings()->setMicrophone( QString::fromStdString(microphones_[microphoneCombo_->currentIndex()])); if (cameraCombo_) { - settings->setCamera( + ChatPage::instance()->userSettings()->setCamera( QString::fromStdString(cameras_[cameraCombo_->currentIndex()])); } emit accept(); diff --git a/src/dialogs/AcceptCall.h b/src/dialogs/AcceptCall.h index 00616c53..76ca7ae1 100644 --- a/src/dialogs/AcceptCall.h +++ b/src/dialogs/AcceptCall.h @@ -3,13 +3,11 @@ #include #include -#include #include class QComboBox; class QPushButton; class QString; -class UserSettings; namespace dialogs { @@ -22,7 +20,6 @@ public: const QString &displayName, const QString &roomName, const QString &avatarUrl, - QSharedPointer settings, bool isVideo, QWidget *parent = nullptr); -- cgit 1.5.1