diff --git a/src/api/lrc.h b/src/api/lrc.h index aec00d77a1adcc912c94cfa6ad8dfd7bef2c4783..f11c94d8fb52b19d182a0a25ae792df3e6d28fe3 100644 --- a/src/api/lrc.h +++ b/src/api/lrc.h @@ -91,10 +91,25 @@ public: void subscribeToDebugReceived(); /** - * Helper: get call list from daemon + * Helper: get active call list from daemon */ static std::vector<std::string> activeCalls(); + /** + * Helper: get call list from daemon + */ + static std::vector<std::string> getCalls(); + + /** + * Helper: get conference list from daemon + */ + static std::vector<std::string> getConferences(); + + /** + * Helper: get subcalls list for a conference from daemon + */ + static std::vector<std::string> getConferenceSubcalls(const std::string& id); + private: std::unique_ptr<LrcPimpl> lrcPimpl_; }; diff --git a/src/conversationmodel.cpp b/src/conversationmodel.cpp index 918e1b71f94b440b806f451bb14b6d37d550b53a..a8d406b717fe02a2a05919c7e4e86728f89a64ef 100644 --- a/src/conversationmodel.cpp +++ b/src/conversationmodel.cpp @@ -1510,7 +1510,25 @@ ConversationModelPimpl::slotCallStatusChanged(const std::string& callId, int cod return conversation.callId == callId; }); - if (i == conversations.end()) return; + if (i == conversations.end()) { + // In this case, the user didn't pass through placeCall + // This means that a participant was invited to a call + // or a call was placed via dbus. + // We have to update the model + try { + auto call = linked.owner.callModel->getCall(callId); + for (auto& conversation: conversations) { + if (conversation.participants.front() == call.peerUri) { + conversation.callId = callId; + dirtyConversations = {true, true}; + emit linked.conversationUpdated(conversation.uid); + } + } + } catch (std::out_of_range& e) { + qDebug() << "ConversationModelPimpl::slotCallStatusChanged can't get inexistant call"; + } + return; + } auto& conversation = *i; auto uid = conversation.uid; @@ -1668,7 +1686,7 @@ void ConversationModelPimpl::slotCallAddedToConference(const std::string& callId, const std::string& confId) { for (auto& conversation: conversations) { - if (conversation.callId == callId) { + if (conversation.callId == callId || conversation.confId == confId) { conversation.confId = confId; dirtyConversations = {true, true}; emit linked.selectConversation(conversation.uid); diff --git a/src/lrc.cpp b/src/lrc.cpp index 91acd433715df2e0763ea8ffc1749ac137631a96..cbb795ec0aab421e8a8600cc362e0d295e67d103 100644 --- a/src/lrc.cpp +++ b/src/lrc.cpp @@ -149,6 +149,42 @@ Lrc::activeCalls() return result; } +std::vector<std::string> +Lrc::getCalls() +{ + QStringList callLists = CallManager::instance().getCallList(); + std::vector<std::string> result; + result.reserve(callLists.size()); + for (const auto &call : callLists) { + result.emplace_back(call.toStdString()); + } + return result; +} + +std::vector<std::string> +Lrc::getConferences() +{ + QStringList conferencesList = CallManager::instance().getConferenceList(); + std::vector<std::string> result; + result.reserve(conferencesList.size()); + for (const auto &conf : conferencesList) { + result.emplace_back(conf.toStdString()); + } + return result; +} + +std::vector<std::string> +Lrc::getConferenceSubcalls(const std::string& cid) +{ + QStringList callList = CallManager::instance().getParticipantList(cid.c_str()); + std::vector<std::string> result; + result.reserve(callList.size()); + foreach(const auto& callId, callList) { + result.emplace_back(callId.toStdString()); + } + return result; +} + bool isFinished(const QString& callState) { diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp index b75425ae1b3b739bf1e1cb42c1c8f3579d7c7059..1d3b5712da1cb0717b228cef7762b67306e7c0ba 100644 --- a/src/newcallmodel.cpp +++ b/src/newcallmodel.cpp @@ -207,9 +207,12 @@ NewCallModel::getConferenceFromURI(const std::string& uri) const if (call.second->type == call::Type::CONFERENCE) { QStringList callList = CallManager::instance().getParticipantList(call.first.c_str()); foreach(const auto& callId, callList) { - if (pimpl_->calls[callId.toStdString()]->peerUri == uri) { - return *call.second; - } + try { + if (pimpl_->calls.find(callId.toStdString()) != pimpl_->calls.end() + && pimpl_->calls[callId.toStdString()]->peerUri == uri) { + return *call.second; + } + } catch (...) {} } } } @@ -372,18 +375,70 @@ NewCallModel::transferToCall(const std::string& callId, const std::string& callI void NewCallModel::joinCalls(const std::string& callIdA, const std::string& callIdB) const { - if (!hasCall(callIdA) || !hasCall(callIdB)) return; - - auto& call1 = pimpl_->calls[callIdA]; - auto& call2 = pimpl_->calls[callIdB]; - if (call1->type == call::Type::CONFERENCE && call2->type == call::Type::CONFERENCE) - CallManager::instance().joinConference(callIdA.c_str(), callIdB.c_str()); - else if (call1->type == call::Type::CONFERENCE) - CallManager::instance().addParticipant(callIdB.c_str(), callIdA.c_str()); - else if (call2->type == call::Type::CONFERENCE) - CallManager::instance().addParticipant(callIdA.c_str(), callIdB.c_str()); - else + // Get call informations + call::Info call1, call2; + std::string accountIdCall1 = {}, accountIdCall2 = {}; + for (const auto &account_id : owner.accountModel->getAccountList()) { + try { + auto &accountInfo = owner.accountModel->getAccountInfo(account_id); + if (accountInfo.callModel->hasCall(callIdA)) { + call1 = accountInfo.callModel->getCall(callIdA); + accountIdCall1 = account_id; + } + if (accountInfo.callModel->hasCall(callIdB)) { + call2 = accountInfo.callModel->getCall(callIdB); + accountIdCall2 = account_id; + } + if (!accountIdCall1.empty() && !accountIdCall2.empty()) break; + } catch (...) {} + } + if (accountIdCall1.empty() || accountIdCall2.empty()) { + qWarning() << "Can't join inexistent calls."; + return; + } + + if (call1.type == call::Type::CONFERENCE && call2.type == call::Type::CONFERENCE) { + bool joined = CallManager::instance().joinConference(callIdA.c_str(), callIdB.c_str()); + + if (!joined) { + qWarning() << "Conference: " << callIdA.c_str() << " couldn't join conference " << callIdB.c_str(); + return; + } + if (accountIdCall1 != owner.id) { + // If the conference is added from another account + try { + auto &accountInfo = owner.accountModel->getAccountInfo(accountIdCall1); + if (accountInfo.callModel->hasCall(callIdA)) { + emit accountInfo.callModel->callAddedToConference(callIdA, callIdB); + } + } catch (...) {} + } else { + emit callAddedToConference(callIdA, callIdB); + } + } else if (call1.type == call::Type::CONFERENCE || call2.type == call::Type::CONFERENCE) { + auto call = call1.type == call::Type::CONFERENCE ? callIdB : callIdA; + auto conf = call1.type == call::Type::CONFERENCE ? callIdA : callIdB; + auto accountCall = call1.type == call::Type::CONFERENCE ? accountIdCall2 : accountIdCall1; + bool joined = CallManager::instance().addParticipant(call.c_str(), conf.c_str()); + if (!joined) { + qWarning() << "Call: " << call.c_str() << " couldn't join conference " << conf.c_str(); + return; + } + if (accountCall != owner.id) { + // If the call is added from another account + try { + auto &accountInfo = owner.accountModel->getAccountInfo(accountCall); + if (accountInfo.callModel->hasCall(call)) { + accountInfo.callModel->pimpl_->slotConferenceCreated(conf); + } + } catch (...) {} + } else + emit callAddedToConference(call, conf); + } + else { CallManager::instance().joinParticipant(callIdA.c_str(), callIdB.c_str()); + // NOTE: This will trigger slotConferenceCreated. + } } void