diff --git a/src/api/call.h b/src/api/call.h index d7a2da2bfadc5d2f292a82aff492416865101f4b..922449ce8d0228f1d6901025c2c6061e535c801c 100644 --- a/src/api/call.h +++ b/src/api/call.h @@ -138,6 +138,7 @@ struct Info bool isAudioOnly = false; Layout layout = Layout::GRID; VectorMapStringString participantsInfos = {}; + VectorMapStringString mediaList = {}; QSet<QString> peerRec {}; }; diff --git a/src/api/newcallmodel.h b/src/api/newcallmodel.h index 8c5c3d8113ed3264a4989f55f4056b69adc78d4f..124b77af092e92f40ecd8653a05b1ee41b61cfab 100644 --- a/src/api/newcallmodel.h +++ b/src/api/newcallmodel.h @@ -234,6 +234,14 @@ public: */ void setCurrentCall(const QString& callId) const; + /** + * Update call mediaList to be used in the call answering + * + * @param callId + * @param acceptVideo + */ + void updateCallMediaList(const QString& callId, bool acceptVideo); + /** * Change the conference layout */ diff --git a/src/callbackshandler.cpp b/src/callbackshandler.cpp index 54777d5b20420259e12707b66fb84ae436f4a257..419800d7e5b495d401263c6b7455f6e887245e8d 100644 --- a/src/callbackshandler.cpp +++ b/src/callbackshandler.cpp @@ -120,6 +120,12 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) &CallbacksHandler::slotIncomingCall, Qt::QueuedConnection); + connect(&CallManager::instance(), + &CallManagerInterface::incomingCallWithMedia, + this, + &CallbacksHandler::slotIncomingCallWithMedia, + Qt::QueuedConnection); + connect(&CallManager::instance(), &CallManagerInterface::callStateChanged, this, @@ -333,6 +339,15 @@ void CallbacksHandler::slotIncomingCall(const QString& accountId, const QString& callId, const QString& fromUri) +{ + slotIncomingCallWithMedia(accountId, callId, fromUri, {}); +} + +void +CallbacksHandler::slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const VectorMapStringString& mediaList) { QString displayname; QString fromQString; @@ -349,7 +364,7 @@ CallbacksHandler::slotIncomingCall(const QString& accountId, fromQString = fromUri.mid(left, right - left); displayname = fromUri.left(fromUri.indexOf("<") - 1); } - emit incomingCall(accountId, callId, fromQString, displayname); + emit incomingCallWithMedia(accountId, callId, fromQString, displayname, mediaList); } void diff --git a/src/callbackshandler.h b/src/callbackshandler.h index 90de27d2ac21f8e08e7c252d7fdbd57e919e6ea4..e06be5ab47f5992730c8be2a8dad713f3d986182 100644 --- a/src/callbackshandler.h +++ b/src/callbackshandler.h @@ -105,11 +105,13 @@ Q_SIGNALS: * @param callId the call id * @param fromUri the caller uri * @param displayName the display name of incoming call + * @param mediaList media received */ - void incomingCall(const QString& accountId, - const QString& callId, - const QString& fromUri, - const QString& displayName); + void incomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const QString& displayName, + const VectorMapStringString& mediaList); /** * Connect this signal to know when a call is updated * @param callId the call id @@ -390,12 +392,24 @@ private Q_SLOTS: unsigned detail_code, const QString& detail_str); /** + * @deprecated Use slotIncomingCallWithMedia instead * Get the URI of the peer and emit incomingCall * @param accountId account linked * @param callId the incoming call id * @param fromQString the uri of the peer */ void slotIncomingCall(const QString& accountId, const QString& callId, const QString& fromUri); + /** + * Get the URI of the peer and emit incomingCallWithMedia + * @param accountId account linked + * @param callId the incoming call id + * @param fromQString the uri of the peer + * @param mediaList the mediaList received + */ + void slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const VectorMapStringString& mediaList); /** * Emit callStateChanged * @param callId the call which changes. diff --git a/src/newcallmodel.cpp b/src/newcallmodel.cpp index 44b168836b63ad86d2aa584c1961104e14579d35..e7c4e3a2e9fbc71c09a98cc0e796245d79b9bd90 100644 --- a/src/newcallmodel.cpp +++ b/src/newcallmodel.cpp @@ -157,11 +157,13 @@ public Q_SLOTS: * @param callId * @param fromId peer uri * @param displayname + * @param mediaList media received */ - void slotIncomingCall(const QString& accountId, - const QString& callId, - const QString& fromId, - const QString& displayname); + void slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromId, + const QString& displayname, + const VectorMapStringString& mediaList); /** * Listen from CallbacksHandler when a call got a new state * @param callId @@ -263,20 +265,46 @@ NewCallModel::getCall(const QString& uid) const return *pimpl_->calls.at(uid); } +void +NewCallModel::updateCallMediaList(const QString& callId, bool acceptVideo) +{ + try { + auto callInfos = pimpl_->calls.find(callId); + if (callInfos != pimpl_->calls.end()) { + for (auto it = callInfos->second->mediaList.begin(); + it != callInfos->second->mediaList.end(); + it++) { + if ((*it)["MEDIA_TYPE"] == "MEDIA_TYPE_VIDEO" && !acceptVideo) { + (*it)["ENABLED"] = "true"; + (*it)["MUTED"] = "true"; + callInfos->second->videoMuted = !acceptVideo; + } + } + } + } catch (...) { + } +} + QString NewCallModel::createCall(const QString& uri, bool isAudioOnly) { + VectorMapStringString mediaList {}; + MapStringString mediaAttribute = {{"MEDIA_TYPE", "MEDIA_TYPE_AUDIO"}, + {"ENABLED", "true"}, + {"MUTED", "false"}, + {"SOURCE", ""}, + {"LABEL", "main_audio"}}; + mediaList.push_back(mediaAttribute); + if (!isAudioOnly) { + mediaAttribute["MEDIA_TYPE"] = "MEDIA_TYPE_VIDEO"; + mediaAttribute["LABEL"] = "main_video"; + mediaList.push_back(mediaAttribute); + } #ifdef ENABLE_LIBWRAP - auto callId = isAudioOnly - ? CallManager::instance().placeCall(owner.id, uri, {{"AUDIO_ONLY", "true"}}) - : CallManager::instance().placeCall(owner.id, uri); -#else // dbus + auto callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList); +#else // dbus // do not use auto here (QDBusPendingReply<QString>) - QString callId = isAudioOnly - ? CallManager::instance().placeCallWithDetails(owner.id, - uri, - {{"AUDIO_ONLY", "true"}}) - : CallManager::instance().placeCall(owner.id, uri); + QString callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList); #endif // ENABLE_LIBWRAP if (callId.isEmpty()) { @@ -291,6 +319,7 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly) callInfo->status = call::Status::SEARCHING; callInfo->type = call::Type::DIALOG; callInfo->isAudioOnly = isAudioOnly; + callInfo->mediaList = mediaList; pimpl_->calls.emplace(callId, std::move(callInfo)); return callId; @@ -299,7 +328,16 @@ NewCallModel::createCall(const QString& uri, bool isAudioOnly) void NewCallModel::accept(const QString& callId) const { - CallManager::instance().accept(callId); + try { + auto& callInfo = pimpl_->calls[callId]; + if (!callInfo) + return; + if (callInfo->mediaList.empty()) + CallManager::instance().accept(callId); + else + CallManager::instance().acceptWithMedia(callId, callInfo->mediaList); + } catch (...) { + } } void @@ -571,9 +609,9 @@ NewCallModelPimpl::NewCallModelPimpl(const NewCallModel& linked, , behaviorController(behaviorController) { connect(&callbacksHandler, - &CallbacksHandler::incomingCall, + &CallbacksHandler::incomingCallWithMedia, this, - &NewCallModelPimpl::slotIncomingCall); + &NewCallModelPimpl::slotIncomingCallWithMedia); connect(&callbacksHandler, &CallbacksHandler::callStateChanged, this, @@ -845,10 +883,11 @@ NewCallModel::isConferenceHost(const QString& callId) } void -NewCallModelPimpl::slotIncomingCall(const QString& accountId, - const QString& callId, - const QString& fromId, - const QString& displayname) +NewCallModelPimpl::slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromId, + const QString& displayname, + const VectorMapStringString& mediaList) { if (linked.owner.id != accountId) { return; @@ -874,6 +913,7 @@ NewCallModelPimpl::slotIncomingCall(const QString& accountId, callInfo->status = call::Status::INCOMING_RINGING; callInfo->type = call::Type::DIALOG; callInfo->isAudioOnly = callDetails["AUDIO_ONLY"] == "true" ? true : false; + callInfo->mediaList = mediaList; calls.emplace(callId, std::move(callInfo)); if (!linked.owner.confProperties.allowIncoming @@ -885,7 +925,7 @@ NewCallModelPimpl::slotIncomingCall(const QString& accountId, emit linked.newIncomingCall(fromId, callId, displayname); // HACK. BECAUSE THE DAEMON DOESN'T HANDLE THIS CASE! - if (linked.owner.confProperties.autoAnswer) { + if (!linked.owner.confProperties.isRendezVous && linked.owner.confProperties.autoAnswer) { linked.accept(callId); } } diff --git a/src/qtwrapper/callmanager_wrap.h b/src/qtwrapper/callmanager_wrap.h index 1de7a7fa7ee0e7d2a41ac33327b104e7d70332b3..e2ac06831c5d55067b11905242982db364bc72da 100644 --- a/src/qtwrapper/callmanager_wrap.h +++ b/src/qtwrapper/callmanager_wrap.h @@ -103,6 +103,21 @@ public: QString(callID.c_str()), QString(from.c_str())); }), + exportable_callback<CallSignal::IncomingCallWithMedia>( + [this](const std::string& accountID, + const std::string& callID, + const std::string& from, + const std::vector<std::map<std::string, std::string>>& mediaList) { + LOG_DRING_SIGNAL4("incomingCallWithMedia", + QString(accountID.c_str()), + QString(callID.c_str()), + QString(from.c_str()), + convertVecMap(mediaList)); + Q_EMIT incomingCallWithMedia(QString(accountID.c_str()), + QString(callID.c_str()), + QString(from.c_str()), + convertVecMap(mediaList)); + }), exportable_callback<CallSignal::RecordPlaybackFilepath>( [this](const std::string& callID, const std::string& filepath) { LOG_DRING_SIGNAL2("recordPlaybackFilepath", @@ -172,9 +187,7 @@ public: Q_EMIT smartInfo(convertMap(info)); }), exportable_callback<CallSignal::RemoteRecordingChanged>( - [this](const std::string &callID, - const std::string &contactId, - bool state) { + [this](const std::string& callID, const std::string& contactId, bool state) { LOG_DRING_SIGNAL3("remoteRecordingChanged", QString(callID.c_str()), QString(contactId.c_str()), @@ -315,6 +328,34 @@ public Q_SLOTS: // METHODS return temp; } + // MULTISTREAM FUNCTIONS + QString placeCallWithMedia(const QString& accountID, + const QString& to, + const VectorMapStringString& mediaList) + { + QString temp(DRing::placeCallWithMedia(accountID.toStdString(), + to.toStdString(), + convertVecMap(mediaList)) + .c_str()); + return temp; + } + + bool requestMediaChange(const QString& callID, const VectorMapStringString& mediaList) + { + return DRing::requestMediaChange(callID.toStdString(), convertVecMap(mediaList)); + } + + bool acceptWithMedia(const QString& callID, const VectorMapStringString& mediaList) + { + return DRing::acceptWithMedia(callID.toStdString(), convertVecMap(mediaList)); + } + + bool answerMediaChangeRequest(const QString& callID, const VectorMapStringString& mediaList) + { + return DRing::answerMediaChangeRequest(callID.toStdString(), convertVecMap(mediaList)); + } + // END OF MULTISTREAM FUNCTIONS + void playDTMF(const QString& key) { DRing::playDTMF(key.toStdString()); } void recordPlaybackSeek(double value) { DRing::recordPlaybackSeek(value); } @@ -409,6 +450,10 @@ Q_SIGNALS: // SIGNALS void voiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount); void incomingMessage(const QString& callID, const QString& from, const MapStringString& message); void incomingCall(const QString& accountID, const QString& callID, const QString& from); + void incomingCallWithMedia(const QString& accountID, + const QString& callID, + const QString& from, + const VectorMapStringString& mediaList); void recordPlaybackFilepath(const QString& callID, const QString& filepath); void conferenceCreated(const QString& confID); void conferenceChanged(const QString& confID, const QString& state); @@ -421,7 +466,9 @@ Q_SIGNALS: // SIGNALS void videoMuted(const QString& callID, bool state); void peerHold(const QString& callID, bool state); void smartInfo(const MapStringString& info); - void remoteRecordingChanged(const QString &callID, const QString &peerNumber, bool remoteRecordingState); + void remoteRecordingChanged(const QString& callID, + const QString& peerNumber, + bool remoteRecordingState); }; namespace org { diff --git a/src/qtwrapper/conversions_wrap.hpp b/src/qtwrapper/conversions_wrap.hpp index 965a8e115d1c1da739e9817819ea183e2016dc36..6d4dc42807f97fa5d3c679e6e273e7791e32f0d4 100644 --- a/src/qtwrapper/conversions_wrap.hpp +++ b/src/qtwrapper/conversions_wrap.hpp @@ -73,6 +73,16 @@ convertVecMap(const std::vector<std::map<std::string, std::string>>& m) return temp; } +inline std::vector<std::map<std::string, std::string>> +convertVecMap(const VectorMapStringString& m) +{ + std::vector<std::map<std::string, std::string>> temp; + for (const auto& x : m) { + temp.push_back(convertMap(x)); + } + return temp; +} + inline QStringList convertStringList(const std::vector<std::string>& v) {