From 536a67652da1579ee190bd34b4be759c181bf7a6 Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Wed, 9 Oct 2024 18:40:03 +0200 Subject: [PATCH] fix #LINQT-1338 custom error message in call window --- Linphone/core/call/CallCore.cpp | 12 ++-- Linphone/core/call/CallCore.hpp | 2 +- Linphone/model/call/CallModel.cpp | 26 ++++++++- Linphone/model/call/CallModel.hpp | 3 + Linphone/tool/LinphoneEnums.cpp | 9 +++ Linphone/tool/LinphoneEnums.hpp | 32 +++++++++++ .../Control/Container/Call/CallLayout.qml | 56 ++++++------------- .../view/Page/Window/Call/CallsWindow.qml | 2 +- 8 files changed, 93 insertions(+), 49 deletions(-) diff --git a/Linphone/core/call/CallCore.cpp b/Linphone/core/call/CallCore.cpp index 9cf0df033..e135d3211 100644 --- a/Linphone/core/call/CallCore.cpp +++ b/Linphone/core/call/CallCore.cpp @@ -257,12 +257,11 @@ void CallCore::setSelf(QSharedPointer me) { mCallModelConnection->makeConnectToModel(&CallModel::microphoneVolumeChanged, [this](float volume) { mCallModelConnection->invokeToCore([this, volume]() { setMicrophoneVolume(volume); }); }); + mCallModelConnection->makeConnectToModel( + &CallModel::errorMessageChanged, [this](const QString &errorMessage) { setLastErrorMessage(errorMessage); }); mCallModelConnection->makeConnectToModel(&CallModel::stateChanged, [this](std::shared_ptr call, linphone::Call::State state, const std::string &message) { - mCallModelConnection->invokeToCore([this, state, message]() { - setState(LinphoneEnums::fromLinphone(state), Utils::coreStringToAppString(message)); - }); double speakerVolume = mSpeakerVolumeGain; double micVolumeGain = mMicrophoneVolumeGain; if (state == linphone::Call::State::StreamsRunning) { @@ -283,6 +282,7 @@ void CallCore::setSelf(QSharedPointer me) { setPaused(state == linphone::Call::State::Paused || state == linphone::Call::State::PausedByRemote); if (mConference) mConference->setSubject(subject); }); + mCallModelConnection->invokeToCore([this, state, message]() { setState(LinphoneEnums::fromLinphone(state)); }); }); mCallModelConnection->makeConnectToModel(&CallModel::statusChanged, [this](linphone::Call::Status status) { mCallModelConnection->invokeToCore([this, status]() { setStatus(LinphoneEnums::fromLinphone(status)); }); @@ -492,14 +492,10 @@ LinphoneEnums::CallState CallCore::getState() const { return mState; } -void CallCore::setState(LinphoneEnums::CallState state, const QString &message) { +void CallCore::setState(LinphoneEnums::CallState state) { mustBeInMainThread(log().arg(Q_FUNC_INFO)); if (mState != state) { mState = state; - if (state == LinphoneEnums::CallState::Error) { - lDebug() << "[CallCore] Error message : " << message; - setLastErrorMessage(message); - } emit stateChanged(mState); } } diff --git a/Linphone/core/call/CallCore.hpp b/Linphone/core/call/CallCore.hpp index 38cad83d2..2ed1356ca 100644 --- a/Linphone/core/call/CallCore.hpp +++ b/Linphone/core/call/CallCore.hpp @@ -154,7 +154,7 @@ public: void setDir(LinphoneEnums::CallDir dir); LinphoneEnums::CallState getState() const; - void setState(LinphoneEnums::CallState state, const QString &message); + void setState(LinphoneEnums::CallState state); QString getLastErrorMessage() const; void setLastErrorMessage(const QString &message); diff --git a/Linphone/model/call/CallModel.cpp b/Linphone/model/call/CallModel.cpp index ca5fb056a..1cf5062ed 100644 --- a/Linphone/model/call/CallModel.cpp +++ b/Linphone/model/call/CallModel.cpp @@ -388,6 +388,29 @@ void CallModel::sendDtmf(const QString &dtmf) { CoreModel::getInstance()->getCore()->playDtmf(key, gDtmfSoundDelay); } +void CallModel::updateCallErrorFromReason(linphone::Reason reason) { + QString error; + switch (reason) { + case linphone::Reason::Declined: + error = tr("Le correspondant a décliné l'appel"); + break; + case linphone::Reason::NotFound: + error = tr("Le correspondant n'a pas été trouvé"); + break; + case linphone::Reason::Busy: + error = tr("Le correspondant est occupé"); + break; + case linphone::Reason::NotAcceptable: + error = tr("Le correspondant ne peut accepter votre appel."); + break; + default: + break; + } + + if (!error.isEmpty()) qInfo() << QStringLiteral("Call terminated with error (%1):").arg(error) << this; + emit errorMessageChanged(error); +} + void CallModel::onDtmfReceived(const std::shared_ptr &call, int dtmf) { CoreModel::getInstance()->getCore()->playDtmf(dtmf, gDtmfSoundDelay); emit dtmfReceived(call, dtmf); @@ -431,8 +454,9 @@ void CallModel::onStateChanged(const std::shared_ptr &call, videoDirection == linphone::MediaDirection::SendRecv); setConference(call->getConference()); updateConferenceVideoLayout(); - } else if (state == linphone::Call::State::End) { + } else if (state == linphone::Call::State::End || state == linphone::Call::State::Error) { mDurationTimer.stop(); + updateCallErrorFromReason(call->getReason()); } emit stateChanged(call, state, message); } diff --git a/Linphone/model/call/CallModel.hpp b/Linphone/model/call/CallModel.hpp index c14d703b3..64bd96e1a 100644 --- a/Linphone/model/call/CallModel.hpp +++ b/Linphone/model/call/CallModel.hpp @@ -90,6 +90,8 @@ public: void sendDtmf(const QString &dtmf); + void updateCallErrorFromReason(linphone::Reason reason); + signals: void microphoneMutedChanged(bool isMuted); void speakerMutedChanged(bool isMuted); @@ -107,6 +109,7 @@ signals: void conferenceChanged(); void conferenceVideoLayoutChanged(LinphoneEnums::ConferenceLayout layout); void videoDescriptorChanged(); + void errorMessageChanged(const QString &error); private: QTimer mDurationTimer; diff --git a/Linphone/tool/LinphoneEnums.cpp b/Linphone/tool/LinphoneEnums.cpp index a8901345b..bae99a7cf 100644 --- a/Linphone/tool/LinphoneEnums.cpp +++ b/Linphone/tool/LinphoneEnums.cpp @@ -148,6 +148,7 @@ LinphoneEnums::CallDir LinphoneEnums::fromLinphone(const linphone::Call::Dir &da linphone::Call::Dir LinphoneEnums::toLinphone(const LinphoneEnums::CallDir &data) { return static_cast(data); } + QString LinphoneEnums::toString(const LinphoneEnums::CallDir &data) { switch (data) { case LinphoneEnums::CallDir::Incoming: @@ -159,6 +160,14 @@ QString LinphoneEnums::toString(const LinphoneEnums::CallDir &data) { } } +LinphoneEnums::Reason LinphoneEnums::fromLinphone(const linphone::Reason &data) { + return static_cast(data); +} + +linphone::Reason LinphoneEnums::toLinphone(const LinphoneEnums::Reason &data) { + return static_cast(data); +} + linphone::Conference::Layout LinphoneEnums::toLinphone(const LinphoneEnums::ConferenceLayout &layout) { if (layout != LinphoneEnums::ConferenceLayout::AudioOnly) return static_cast(layout); else return linphone::Conference::Layout::Grid; // Audio Only mode diff --git a/Linphone/tool/LinphoneEnums.hpp b/Linphone/tool/LinphoneEnums.hpp index 8875588b6..31ab27cb6 100644 --- a/Linphone/tool/LinphoneEnums.hpp +++ b/Linphone/tool/LinphoneEnums.hpp @@ -179,6 +179,38 @@ linphone::Call::Dir toLinphone(const LinphoneEnums::CallDir &data); LinphoneEnums::CallDir fromLinphone(const linphone::Call::Dir &data); QString toString(const LinphoneEnums::CallDir &data); +enum class Reason { + None = int(linphone::Reason::None), + NoResponse = int(linphone::Reason::NoResponse), + Forbidden = int(linphone::Reason::Forbidden), + Declined = int(linphone::Reason::Declined), + NotFound = int(linphone::Reason::NotFound), + NotAnswered = int(linphone::Reason::NotAnswered), + Busy = int(linphone::Reason::Busy), + UnsupportedContent = int(linphone::Reason::UnsupportedContent), + BadEvent = int(linphone::Reason::BadEvent), + IOError = int(linphone::Reason::IOError), + DoNotDisturb = int(linphone::Reason::DoNotDisturb), + Unauthorized = int(linphone::Reason::Unauthorized), + NotAcceptable = int(linphone::Reason::NotAcceptable), + NoMatch = int(linphone::Reason::NoMatch), + MovedPermanently = int(linphone::Reason::MovedPermanently), + Gone = int(linphone::Reason::Gone), + TemporarilyUnavailable = int(linphone::Reason::TemporarilyUnavailable), + AddressIncomplete = int(linphone::Reason::AddressIncomplete), + NotImplemented = int(linphone::Reason::NotImplemented), + BadGateway = int(linphone::Reason::BadGateway), + SessionIntervalTooSmall = int(linphone::Reason::SessionIntervalTooSmall), + ServerTimeout = int(linphone::Reason::ServerTimeout), + Unknown = int(linphone::Reason::Unknown), + Transferred = int(linphone::Reason::Transferred), + ConditionalRequestFailed = int(linphone::Reason::ConditionalRequestFailed), + SasCheckRequired = int(linphone::Reason::SasCheckRequired) +}; +Q_ENUM_NS(Reason) +linphone::Reason toLinphone(const LinphoneEnums::Reason &data); +LinphoneEnums::Reason fromLinphone(const linphone::Reason &data); + enum class ConferenceLayout { Grid = int(linphone::Conference::Layout::Grid), ActiveSpeaker = int(linphone::Conference::Layout::ActiveSpeaker), diff --git a/Linphone/view/Control/Container/Call/CallLayout.qml b/Linphone/view/Control/Container/Call/CallLayout.qml index ca8689a53..be75d122c 100644 --- a/Linphone/view/Control/Container/Call/CallLayout.qml +++ b/Linphone/view/Control/Container/Call/CallLayout.qml @@ -14,7 +14,9 @@ Item { property CallGui call property ConferenceGui conference: call && call.core.conference property bool callTerminatedByUser: false + property bool callStarted: false readonly property var callState: call && call.core.state || undefined + onCallStateChanged: if (callState === LinphoneEnums.CallState.Connected) callStarted = true property int conferenceLayout: call && call.core.conferenceVideoLayout || 0 // property int participantDeviceCount: conference ? conference.core.participantDeviceCount : -1 // onParticipantDeviceCountChanged: { @@ -25,15 +27,6 @@ Item { console.log("CallLayout change : " +conferenceLayout) setConferenceLayout() } - onCallStateChanged: { - if( callState === LinphoneEnums.CallState.Error) { - centerLayout.currentIndex = 1 - } - // else if( callState === LinphoneEnums.CallState.End) { - // callTerminatedText.visible = true - // } - } - // onCallChanged: callTerminatedText.visible = false function setConferenceLayout() { callLayout.sourceComponent = undefined // unload old view before opening the new view to avoid conflicts in Video UI. @@ -48,12 +41,16 @@ Item { anchors.top: parent.top anchors.topMargin: 25 * DefaultStyle.dp z: 1 - visible: callState === LinphoneEnums.CallState.End - text: mainItem.conference - ? qsTr("Vous avez quitté la conférence") - : mainItem.callTerminatedByUser - ? qsTr("Vous avez terminé l'appel") - : qsTr("Votre correspondant a terminé l'appel") + visible: callState === LinphoneEnums.CallState.End || callState === LinphoneEnums.CallState.Error || callState === LinphoneEnums.CallState.Released + text: callState === LinphoneEnums.CallState.End + ? mainItem.conference + ? qsTr("Vous avez quitté la conférence") + : mainItem.callStarted + ? mainItem.callTerminatedByUser + ? qsTr("Vous avez terminé l'appel") + : qsTr("Votre correspondant a terminé l'appel") + : call.core.lastErrorMessage + : call.core.lastErrorMessage color: DefaultStyle.grey_0 font { pixelSize: 22 * DefaultStyle.dp @@ -61,31 +58,14 @@ Item { } } - Layout.StackLayout { - id: centerLayout - currentIndex: 0 + Loader{ + id: callLayout anchors.fill: parent - Loader{ - id: callLayout - Layout.Layout.fillWidth: true - Layout.Layout.fillHeight: true - sourceComponent: mainItem.participantDeviceCount === 0 - ? waitingForOthersComponent - : activeSpeakerComponent - } - Layout.ColumnLayout { - id: userNotFoundLayout - Layout.Layout.preferredWidth: parent.width - Layout.Layout.preferredHeight: parent.height - Layout.Layout.alignment: Qt.AlignCenter - Text { - text: mainItem.call ? mainItem.call.core.lastErrorMessage : "" - Layout.Layout.alignment: Qt.AlignCenter - color: DefaultStyle.grey_0 - font.pixelSize: 40 * DefaultStyle.dp - } - } + sourceComponent: mainItem.participantDeviceCount === 0 + ? waitingForOthersComponent + : activeSpeakerComponent } + Component{ id: activeSpeakerComponent ActiveSpeakerLayout{ diff --git a/Linphone/view/Page/Window/Call/CallsWindow.qml b/Linphone/view/Page/Window/Call/CallsWindow.qml index b65517806..53c8931d1 100644 --- a/Linphone/view/Page/Window/Call/CallsWindow.qml +++ b/Linphone/view/Page/Window/Call/CallsWindow.qml @@ -139,7 +139,7 @@ AbstractWindow { Timer { id: autoCloseWindow - interval: 2000 + interval: 3000 onTriggered: { UtilsCpp.closeCallsWindow() }