diff --git a/Linphone/model/tool/ToolModel.cpp b/Linphone/model/tool/ToolModel.cpp index 90839d692..7c384d469 100644 --- a/Linphone/model/tool/ToolModel.cpp +++ b/Linphone/model/tool/ToolModel.cpp @@ -166,9 +166,8 @@ bool ToolModel::createCall(const QString &sipAddress, bool isConference = !!core->findConferenceInformationFromUri(address); if (isConference) mediaEncryption = linphone::MediaEncryption::ZRTP; - if (SettingsModel::dndEnabled( - core->getConfig())) { // Force tones for outgoing calls when in DND mode (ringback, dtmf, etc … ) disabled - // again when no more calls are running. + if (SettingsModel::dndEnabled(core->getConfig())) { // Force tones for outgoing calls when in DND mode (ringback, + // dtmf, etc … ) disabled again when no more calls are running. SettingsModel::getInstance()->setCallToneIndicationsEnabled(true); } std::shared_ptr params = core->createCallParams(nullptr); @@ -225,6 +224,47 @@ bool ToolModel::createCall(const QString &sipAddress, */ } +bool ToolModel::createGroupCall(QString subject, const std::list &participantAddresses, QString *message) { + auto core = CoreModel::getInstance()->getCore(); + auto conferenceParams = core->createConferenceParams(nullptr); + conferenceParams->enableVideo(true); + auto account = core->getDefaultAccount(); + if (!account) { + qWarning() << "No default account found, can't create group call"; + *message = tr("group_call_error_no_account"); + return false; + } + conferenceParams->setAccount(account); + conferenceParams->setSubject(Utils::appStringToCoreString(subject)); + + auto createEndToEnd = SettingsModel::getInstance()->getCreateEndToEndEncryptedMeetingsAndGroupCalls(); + conferenceParams->setSecurityLevel(createEndToEnd ? linphone::Conference::SecurityLevel::EndToEnd + : linphone::Conference::SecurityLevel::PointToPoint); + + conferenceParams->enableChat(true); + + auto conference = core->createConferenceWithParams(conferenceParams); + if (conference) { + auto callParams = core->createCallParams(nullptr); + callParams->enableVideo(true); + callParams->setVideoDirection(linphone::MediaDirection::RecvOnly); + std::list> participants; + for (auto &address : participantAddresses) { + auto linAddr = ToolModel::interpretUrl(address); + participants.push_back(linAddr); + } + auto status = conference->inviteParticipants(participants, callParams); + if (status != 0) { + qWarning() << "Failed to invite participants into group call"; + *message = tr("group_call_error_participants_invite"); + } + } else { + qWarning() << "Could not create group call"; + *message = tr("group_call_error_creation"); + } + return conference != nullptr; +} + std::shared_ptr ToolModel::findAccount(const std::shared_ptr &address) { std::shared_ptr account; for (auto item : CoreModel::getInstance()->getCore()->getAccountList()) { @@ -301,11 +341,10 @@ std::shared_ptr ToolModel::getLdapFriendList() { } bool ToolModel::friendIsInFriendList(const std::shared_ptr &friendList, - const std::shared_ptr &f) { + const std::shared_ptr &f) { auto friends = friendList->getFriends(); - auto it = std::find_if(friends.begin(), friends.end(), [f] (std::shared_ptr linFriend) { - return linFriend == f; - }); + auto it = std::find_if(friends.begin(), friends.end(), + [f](std::shared_ptr linFriend) { return linFriend == f; }); return (it != friends.end()); } @@ -361,8 +400,8 @@ QVariantMap ToolModel::createVariant(const std::shared_ptrgetId()) : ""); map.insert("display_name", device ? Utils::coreStringToAppString(device->getDriverName() + ": " + device->getDeviceName()) - //: "Unknown device" - : tr("unknown_audio_device_name")); + //: "Unknown device" + : tr("unknown_audio_device_name")); return map; } diff --git a/Linphone/model/tool/ToolModel.hpp b/Linphone/model/tool/ToolModel.hpp index 55c9e0327..9fdf69918 100644 --- a/Linphone/model/tool/ToolModel.hpp +++ b/Linphone/model/tool/ToolModel.hpp @@ -53,7 +53,6 @@ public: static std::shared_ptr findFriendByAddress(const QString &address); static std::shared_ptr findFriendByAddress(std::shared_ptr linphoneAddr); - static bool createCall(const QString &sipAddress, const QVariantMap &options = {}, const QString &prepareTransfertAddress = "", @@ -61,6 +60,9 @@ public: linphone::MediaEncryption = linphone::MediaEncryption::None, QString *errorMessage = nullptr); + static bool + createGroupCall(QString subject, const std::list &participantAddresses, QString *message = nullptr); + static std::shared_ptr getFriendList(const std::string &listName); static std::shared_ptr getAppFriendList(); static std::shared_ptr getLdapFriendList(); diff --git a/Linphone/tool/Utils.cpp b/Linphone/tool/Utils.cpp index bba126760..15775ceae 100644 --- a/Linphone/tool/Utils.cpp +++ b/Linphone/tool/Utils.cpp @@ -154,6 +154,17 @@ void Utils::createCall(const QString &sipAddress, }); } +void Utils::createGroupCall(QString subject, const std::list &participantAddresses) { + App::postModelAsync([subject, participantAddresses]() { + QString errorMessage; + bool success = ToolModel::createGroupCall(subject, participantAddresses, &errorMessage); + if (!success) { + if (errorMessage.isEmpty()) errorMessage = tr("information_popup_group_call_not_created_message"); + showInformationPopup(tr("information_popup_error_title"), errorMessage, false); + } + }); +} + // TODO : change conf info only from qml // (bug si on est déjà en appel et qu'on lance une conf) // demander à jonhatan pour le design : quand on est déjà en appel @@ -304,9 +315,9 @@ QString Utils::formatDate(const QDateTime &date, bool includeTime, QString forma //: "Hier else if (date.date() == QDate::currentDate().addDays(-1)) dateDay = tr("yesterday"); else { - if(format.isEmpty()) format = date.date().year() == QDateTime::currentDateTime(date.timeZone()).date().year() - ? "dd MMMM" - : "dd MMMM yyyy"; + if (format.isEmpty()) + format = date.date().year() == QDateTime::currentDateTime(date.timeZone()).date().year() ? "dd MMMM" + : "dd MMMM yyyy"; dateDay = App::getInstance()->getLocale().toString(date.date(), format); } if (!includeTime) return dateDay; diff --git a/Linphone/tool/Utils.hpp b/Linphone/tool/Utils.hpp index 000f31e08..50a692636 100644 --- a/Linphone/tool/Utils.hpp +++ b/Linphone/tool/Utils.hpp @@ -71,6 +71,7 @@ public: LinphoneEnums::MediaEncryption mediaEncryption = LinphoneEnums::MediaEncryption::None, const QString &prepareTransfertAddress = "", const QHash &headers = {}); + Q_INVOKABLE static void createGroupCall(QString subject, const std::list &participantAddresses); Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui); Q_INVOKABLE static QQuickWindow *getMainWindow(); Q_INVOKABLE static void openCallsWindow(CallGui *call); @@ -87,7 +88,8 @@ public: Q_INVOKABLE static QString createAvatar(const QUrl &fileUrl); // Return the avatar path Q_INVOKABLE static QString formatElapsedTime(int seconds, bool dotsSeparator = true); // Return the elapsed time formated - Q_INVOKABLE static QString formatDate(const QDateTime &date, bool includeTime = true, QString format = ""); // Return the date formated + Q_INVOKABLE static QString + formatDate(const QDateTime &date, bool includeTime = true, QString format = ""); // Return the date formated Q_INVOKABLE static QString formatDateElapsedTime(const QDateTime &date); Q_INVOKABLE static QString formatTime(const QDateTime &date); // Return the time formated Q_INVOKABLE static QStringList generateSecurityLettersArray(int arraySize, int correctIndex, QString correctCode); @@ -137,7 +139,7 @@ public: Q_INVOKABLE static QString getFileChecksum(const QString &filePath); Q_INVOKABLE QList append(const QList a, const QList b); -// QDir findDirectoryByName(QString startPath, QString name); + // QDir findDirectoryByName(QString startPath, QString name); static QString getApplicationProduct(); static QString getOsProduct(); diff --git a/Linphone/view/Page/Main/Call/CallPage.qml b/Linphone/view/Page/Main/Call/CallPage.qml index d2082a519..23e9c45cd 100644 --- a/Linphone/view/Page/Main/Call/CallPage.qml +++ b/Linphone/view/Page/Main/Call/CallPage.qml @@ -448,8 +448,7 @@ AbstractMainPage { Layout.fillWidth: true Layout.fillHeight: true Layout.topMargin: Math.round(15 * DefaultStyle.dp) - onSelectedParticipantsCountChanged: mainItem.selectedParticipantsCount - = selectedParticipantsCount + onSelectedParticipantsCountChanged: mainItem.selectedParticipantsCount = selectedParticipantsCount focus: true Connections { target: mainItem @@ -457,24 +456,20 @@ AbstractMainPage { if (groupCallName.text.length === 0) { UtilsCpp.showInformationPopup(qsTr("information_popup_error_title"), //: "Un nom doit être donné à l'appel de groupe - qsTr("group_call_error_must_have_name"), - false) + qsTr("group_call_error_must_have_name"), false) } else if (!mainItem.isRegistered) { - UtilsCpp.showInformationPopup( - qsTr("information_popup_error_title"), + UtilsCpp.showInformationPopup(qsTr("information_popup_error_title"), //: "Vous n'etes pas connecté" - qsTr("group_call_error_not_connected"), - false) + qsTr("group_call_error_not_connected"), false) } else { - mainItem.confInfoGui = Qt.createQmlObject( - 'import Linphone -ConferenceInfoGui{ -}', mainItem) - mainItem.confInfoGui.core.subject = groupCallName.text - mainItem.confInfoGui.core.isScheduled = false - mainItem.confInfoGui.core.addParticipants( - addParticipantsLayout.selectedParticipants) - mainItem.confInfoGui.core.save() + // mainItem.confInfoGui = Qt.createQmlObject( + // "import Linphone + // ConferenceInfoGui{}", mainItem) + // mainItem.confInfoGui.core.subject = groupCallName.text + // mainItem.confInfoGui.core.isScheduled = false + // mainItem.confInfoGui.core.addParticipants(addParticipantsLayout.selectedParticipants) + // mainItem.confInfoGui.core.save() + UtilsCpp.createGroupCall(groupCallName.text, addParticipantsLayout.selectedParticipants) } } } diff --git a/Linphone/view/Page/Window/Call/CallsWindow.qml b/Linphone/view/Page/Window/Call/CallsWindow.qml index a7ab1c967..251e3e2a8 100644 --- a/Linphone/view/Page/Window/Call/CallsWindow.qml +++ b/Linphone/view/Page/Window/Call/CallsWindow.qml @@ -439,7 +439,15 @@ AbstractWindow { EffectImage { Layout.preferredWidth: Math.round(15 * DefaultStyle.dp) Layout.preferredHeight: Math.round(15 * DefaultStyle.dp) - colorizationColor: mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp ? DefaultStyle.info_500_main : mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified ? DefaultStyle.warning_600 : DefaultStyle.info_500_main : DefaultStyle.grey_0 : "transparent" + colorizationColor: mainWindow.call + ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp + ? DefaultStyle.info_500_main + : mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp + ? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified + ? DefaultStyle.warning_600 + : DefaultStyle.info_500_main + : DefaultStyle.grey_0 + : "transparent" visible: mainWindow.call imageSource: mainWindow.call ? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp