From 8c037f83c5c3b770e85f10e0b07cec280883cc58 Mon Sep 17 00:00:00 2001 From: trilene Date: Thu, 12 Nov 2020 19:55:35 -0500 Subject: [PATCH] Make incoming call ringtone a user setting --- src/CallManager.cpp | 32 ++++++++++++++++++++---- src/CallManager.h | 3 ++- src/UserSettingsPage.cpp | 54 ++++++++++++++++++++++++++++++++++++++++ src/UserSettingsPage.h | 6 +++++ 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/CallManager.cpp b/src/CallManager.cpp index ac0636e0..89cfeaf9 100644 --- a/src/CallManager.cpp +++ b/src/CallManager.cpp @@ -98,7 +98,7 @@ CallManager::CallManager(QObject *parent) connect(&session_, &WebRTCSession::stateChanged, this, [this](webrtc::State state) { switch (state) { case webrtc::State::DISCONNECTED: - playRingtone("qrc:/media/media/callend.ogg", false); + playRingtone(QUrl("qrc:/media/media/callend.ogg"), false); clear(); break; case webrtc::State::ICEFAILED: { @@ -121,6 +121,24 @@ CallManager::CallManager(QObject *parent) if (status == QMediaPlayer::LoadedMedia) player_.play(); }); + + connect(&player_, + QOverload::of(&QMediaPlayer::error), + [this](QMediaPlayer::Error error) { + stopRingtone(); + switch (error) { + case QMediaPlayer::FormatError: + case QMediaPlayer::ResourceError: + nhlog::ui()->error("WebRTC: valid ringtone file not found"); + break; + case QMediaPlayer::AccessDeniedError: + nhlog::ui()->error("WebRTC: access to ringtone file denied"); + break; + default: + nhlog::ui()->error("WebRTC: unable to play ringtone"); + break; + } + }); } void @@ -153,7 +171,7 @@ CallManager::sendInvite(const QString &roomid, bool isVideo) callPartyName_ = callee.display_name.isEmpty() ? callee.user_id : callee.display_name; callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url); emit newCallParty(); - playRingtone("qrc:/media/media/ringback.ogg", true); + playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true); if (!session_.createOffer(isVideo)) { emit ChatPage::instance()->showNotification("Problem setting up call."); endCall(); @@ -247,7 +265,11 @@ CallManager::handleEvent(const RoomEvent &callInviteEvent) return; } - playRingtone("qrc:/media/media/ring.ogg", true); + const QString &ringtone = ChatPage::instance()->userSettings()->ringtone(); + if (ringtone != "Mute") + playRingtone(ringtone == "Default" ? QUrl("qrc:/media/media/ring.ogg") + : QUrl::fromLocalFile(ringtone), + true); roomid_ = QString::fromStdString(callInviteEvent.room_id); callid_ = callInviteEvent.content.call_id; remoteICECandidates_.clear(); @@ -409,13 +431,13 @@ CallManager::retrieveTurnServer() } void -CallManager::playRingtone(const QString &ringtone, bool repeat) +CallManager::playRingtone(const QUrl &ringtone, bool repeat) { static QMediaPlaylist playlist; playlist.clear(); playlist.setPlaybackMode(repeat ? QMediaPlaylist::CurrentItemInLoop : QMediaPlaylist::CurrentItemOnce); - playlist.addMedia(QUrl(ringtone)); + playlist.addMedia(ringtone); player_.setVolume(100); player_.setPlaylist(&playlist); } diff --git a/src/CallManager.h b/src/CallManager.h index da7569e2..8004e838 100644 --- a/src/CallManager.h +++ b/src/CallManager.h @@ -15,6 +15,7 @@ namespace mtx::responses { struct TurnServer; } +class QUrl; class WebRTCSession; class CallManager : public QObject @@ -69,6 +70,6 @@ private: void generateCallID(); void clear(); void endCall(); - void playRingtone(const QString &ringtone, bool repeat); + void playRingtone(const QUrl &ringtone, bool repeat); void stopRingtone(); }; diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index a5a40111..d82ddbdd 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -83,6 +83,7 @@ UserSettings::load() presence_ = settings.value("user/presence", QVariant::fromValue(Presence::AutomaticPresence)) .value(); + ringtone_ = settings.value("user/ringtone", "Default").toString(); microphone_ = settings.value("user/microphone", QString()).toString(); camera_ = settings.value("user/camera", QString()).toString(); cameraResolution_ = settings.value("user/camera_resolution", QString()).toString(); @@ -321,6 +322,16 @@ UserSettings::setShareKeysWithTrustedUsers(bool shareKeys) save(); } +void +UserSettings::setRingtone(QString ringtone) +{ + if (ringtone == ringtone_) + return; + ringtone_ = ringtone; + emit ringtoneChanged(ringtone); + save(); +} + void UserSettings::setMicrophone(QString microphone) { @@ -450,6 +461,7 @@ UserSettings::save() settings.setValue("font_family", font_); settings.setValue("emoji_font_family", emojiFont_); settings.setValue("presence", QVariant::fromValue(presence_)); + settings.setValue("ringtone", ringtone_); settings.setValue("microphone", microphone_); settings.setValue("camera", camera_); settings.setValue("camera_resolution", cameraResolution_); @@ -530,6 +542,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge fontSizeCombo_ = new QComboBox{this}; fontSelectionCombo_ = new QFontComboBox{this}; emojiFontSelectionCombo_ = new QComboBox{this}; + ringtoneCombo_ = new QComboBox{this}; microphoneCombo_ = new QComboBox{this}; cameraCombo_ = new QComboBox{this}; cameraResolutionCombo_ = new QComboBox{this}; @@ -720,14 +733,26 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge formLayout_->addRow(callsLabel); formLayout_->addRow(new HorizontalLine{this}); + boxWrap(tr("Ringtone"), + ringtoneCombo_, + tr("Set the notification sound to play when a call invite arrives")); boxWrap(tr("Microphone"), microphoneCombo_); boxWrap(tr("Camera"), cameraCombo_); boxWrap(tr("Camera resolution"), cameraResolutionCombo_); boxWrap(tr("Camera frame rate"), cameraFrameRateCombo_); + + ringtoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + ringtoneCombo_->addItem("Mute"); + ringtoneCombo_->addItem("Default"); + ringtoneCombo_->addItem("Other..."); + const QString &ringtone = settings_->ringtone(); + if (!ringtone.isEmpty() && ringtone != "Mute" && ringtone != "Default") + ringtoneCombo_->addItem(ringtone); microphoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); cameraCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); cameraResolutionCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); cameraFrameRateCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents); + boxWrap(tr("Allow fallback call assist server"), useStunServer_, tr("Will use turn.matrix.org as assist when your home server does not offer one.")); @@ -786,6 +811,34 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge static_cast(&QComboBox::currentTextChanged), [this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); }); + connect(ringtoneCombo_, + static_cast(&QComboBox::currentTextChanged), + [this](const QString &ringtone) { + if (ringtone == "Other...") { + QString homeFolder = + QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + auto filepath = QFileDialog::getOpenFileName( + this, tr("Select a file"), homeFolder, tr("All Files (*)")); + if (!filepath.isEmpty()) { + const auto &oldSetting = settings_->ringtone(); + if (oldSetting != "Mute" && oldSetting != "Default") + ringtoneCombo_->removeItem( + ringtoneCombo_->findText(oldSetting)); + settings_->setRingtone(filepath); + ringtoneCombo_->addItem(filepath); + ringtoneCombo_->setCurrentText(filepath); + } else { + ringtoneCombo_->setCurrentText(settings_->ringtone()); + } + } else if (ringtone == "Mute" || ringtone == "Default") { + const auto &oldSetting = settings_->ringtone(); + if (oldSetting != "Mute" && oldSetting != "Default") + ringtoneCombo_->removeItem( + ringtoneCombo_->findText(oldSetting)); + settings_->setRingtone(ringtone); + } + }); + connect(microphoneCombo_, static_cast(&QComboBox::currentTextChanged), [this](const QString µphone) { settings_->setMicrophone(microphone); }); @@ -916,6 +969,7 @@ UserSettingsPage::showEvent(QShowEvent *) utils::restoreCombobox(fontSizeCombo_, QString::number(settings_->fontSize()) + " "); utils::restoreCombobox(scaleFactorCombo_, QString::number(utils::scaleFactor())); utils::restoreCombobox(themeCombo_, settings_->theme()); + utils::restoreCombobox(ringtoneCombo_, settings_->ringtone()); // FIXME: Toggle treats true as "off" trayToggle_->setState(!settings_->tray()); diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index 0bd0ac84..d1ae93f0 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -73,6 +73,7 @@ class UserSettings : public QObject Q_PROPERTY( QString emojiFont READ emojiFont WRITE setEmojiFontFamily NOTIFY emojiFontChanged) Q_PROPERTY(Presence presence READ presence WRITE setPresence NOTIFY presenceChanged) + Q_PROPERTY(QString ringtone READ ringtone WRITE setRingtone NOTIFY ringtoneChanged) Q_PROPERTY(QString microphone READ microphone WRITE setMicrophone NOTIFY microphoneChanged) Q_PROPERTY(QString camera READ camera WRITE setCamera NOTIFY cameraChanged) Q_PROPERTY(QString cameraResolution READ cameraResolution WRITE setCameraResolution NOTIFY @@ -120,6 +121,7 @@ public: void setAvatarCircles(bool state); void setDecryptSidebar(bool state); void setPresence(Presence state); + void setRingtone(QString ringtone); void setMicrophone(QString microphone); void setCamera(QString camera); void setCameraResolution(QString resolution); @@ -152,6 +154,7 @@ public: QString font() const { return font_; } QString emojiFont() const { return emojiFont_; } Presence presence() const { return presence_; } + QString ringtone() const { return ringtone_; } QString microphone() const { return microphone_; } QString camera() const { return camera_; } QString cameraResolution() const { return cameraResolution_; } @@ -181,6 +184,7 @@ signals: void fontChanged(QString state); void emojiFontChanged(QString state); void presenceChanged(Presence state); + void ringtoneChanged(QString ringtone); void microphoneChanged(QString microphone); void cameraChanged(QString camera); void cameraResolutionChanged(QString resolution); @@ -216,6 +220,7 @@ private: QString font_; QString emojiFont_; Presence presence_; + QString ringtone_; QString microphone_; QString camera_; QString cameraResolution_; @@ -286,6 +291,7 @@ private: QComboBox *fontSizeCombo_; QFontComboBox *fontSelectionCombo_; QComboBox *emojiFontSelectionCombo_; + QComboBox *ringtoneCombo_; QComboBox *microphoneCombo_; QComboBox *cameraCombo_; QComboBox *cameraResolutionCombo_;