From c8c0c7e2a74bae277522de10369eccf8bda33c37 Mon Sep 17 00:00:00 2001
From: Nicolas Jager <nicolas.jager@savoirfairelinux.com>
Date: Fri, 24 Nov 2017 11:25:21 -0500
Subject: [PATCH] new placeCall API, bump daemon API to 4.1.0

Add a new placeCall API with possibility to gives call details.
This permits to give information like media preferences before
to start the call.

This changes force a daemon API bump to 4.1.0

Change-Id: I95d3b5480e194ece4a3cdb03436b2e1625eae016
Reviewed-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
---
 bin/dbus/cx.ring.Ring.CallManager.xml | 24 ++++++++++++++++++++
 bin/dbus/dbuscallmanager.cpp          |  7 ++++++
 bin/dbus/dbuscallmanager.h            |  2 ++
 configure.ac                          |  2 +-
 doc/doxygen/core-doc.cfg.in           |  2 +-
 src/account.h                         |  4 ++--
 src/call.cpp                          | 11 ++++++++-
 src/call.h                            |  6 ++++-
 src/call_factory.h                    | 10 +++++----
 src/client/callmanager.cpp            | 12 ++++++++++
 src/dring/callmanager_interface.h     |  1 +
 src/manager.cpp                       | 11 +++++----
 src/manager.h                         | 32 ++++++++++++++-------------
 src/ringdht/ringaccount.cpp           | 12 +++++-----
 src/ringdht/ringaccount.h             |  7 +++---
 src/sip/sipaccount.cpp                | 10 +++++----
 src/sip/sipaccount.h                  |  7 +++---
 src/sip/sipcall.cpp                   |  5 +++--
 src/sip/sipcall.h                     |  3 ++-
 19 files changed, 121 insertions(+), 47 deletions(-)

diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml
index 61ae67b6ca..84a3394518 100644
--- a/bin/dbus/cx.ring.Ring.CallManager.xml
+++ b/bin/dbus/cx.ring.Ring.CallManager.xml
@@ -25,6 +25,30 @@
             <arg type="s" name="callID" direction="out"/>
         </method>
 
+        <method name="placeCallWithDetails" tp:name-for-bindings="placeCallWithDetails">
+            <tp:added version="4.1.0"/>
+            <tp:docstring>
+              <p>This is a method in order to place a new call. This version allows to pass some call details. The call is registered with the daemon using this method.</p>
+            </tp:docstring>
+            <arg type="s" name="accountID" direction="in">
+              <tp:docstring>
+                The ID of the account with which you want to make a call. If the call is to be placed without any account by means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountID. For more details on accounts see the configuration manager interface.
+              </tp:docstring>
+            </arg>
+            <arg type="s" name="to" direction="in">
+              <tp:docstring>
+                If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified.
+              </tp:docstring>
+            </arg>
+            <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="MapStringString"/>
+            <arg type="a{ss}" name="VolatileCallDetails" direction="in">
+              <tp:docstring>
+                TBD.
+              </tp:docstring>
+            </arg>
+            <arg type="s" name="callID" direction="out"/>
+        </method>
+
         <method name="refuse" tp:name-for-bindings="refuse">
             <tp:docstring>
               Refuse an incoming call.
diff --git a/bin/dbus/dbuscallmanager.cpp b/bin/dbus/dbuscallmanager.cpp
index ba13e13fd9..3bbcf45081 100644
--- a/bin/dbus/dbuscallmanager.cpp
+++ b/bin/dbus/dbuscallmanager.cpp
@@ -31,6 +31,13 @@ DBusCallManager::placeCall(const std::string& accountID, const std::string& to)
     return DRing::placeCall(accountID, to);
 }
 
+auto
+DBusCallManager::placeCallWithDetails(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& VolatileCallDetails)
+    -> decltype (DRing::placeCall(accountID, to, VolatileCallDetails))
+{
+    return DRing::placeCall(accountID, to, VolatileCallDetails);
+}
+
 auto
 DBusCallManager::refuse(const std::string& callID) -> decltype(DRing::refuse(callID))
 {
diff --git a/bin/dbus/dbuscallmanager.h b/bin/dbus/dbuscallmanager.h
index db70c044c6..2f50420008 100644
--- a/bin/dbus/dbuscallmanager.h
+++ b/bin/dbus/dbuscallmanager.h
@@ -55,6 +55,8 @@ class DBusCallManager :
 
         // Methods
         std::string placeCall(const std::string& accountID, const std::string& to);
+        std::string placeCallWithDetails(const std::string& accountID, const std::string& to,
+                                         const std::map<std::string, std::string>& VolatileCallDetails);
         bool refuse(const std::string& callID);
         bool accept(const std::string& callID);
         bool hangUp(const std::string& callID);
diff --git a/configure.ac b/configure.ac
index c558fc93bb..b117399a59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Ring - configure.ac for automake 1.9 and autoconf 2.59
 
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.65])
-AC_INIT([Ring Daemon],[4.0.0],[ring@gnu.org],[ring])
+AC_INIT([Ring Daemon],[4.1.0],[ring@gnu.org],[ring])
 
 AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2017]])
 AC_REVISION([$Revision$])
diff --git a/doc/doxygen/core-doc.cfg.in b/doc/doxygen/core-doc.cfg.in
index 72b2eaa2cc..31660777df 100644
--- a/doc/doxygen/core-doc.cfg.in
+++ b/doc/doxygen/core-doc.cfg.in
@@ -31,7 +31,7 @@ PROJECT_NAME           = "Ring Daemon"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 4.0.0
+PROJECT_NUMBER         = 4.1.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer
diff --git a/src/account.h b/src/account.h
index bbad1e2671..331ad3cd48 100644
--- a/src/account.h
+++ b/src/account.h
@@ -142,7 +142,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
          * @param toUrl The address to call
          * @return std::shared_ptr<Call> A pointer on the created call
          */
-        virtual std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl) = 0;
+        virtual std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {}) = 0;
 
         /* Note: we forbid incoming call creation from an instance of Account.
          * This is why no newIncomingCall() method exist here.
@@ -198,7 +198,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
 
         /**
          * Set the registration state of the specified link
-         * @param state	The registration state of underlying VoIPLink
+         * @param state The registration state of underlying VoIPLink
          */
         virtual void setRegistrationState(RegistrationState state, unsigned detail_code=0, const std::string& detail_str={});
 
diff --git a/src/call.cpp b/src/call.cpp
index db4bee11e6..55fc79afd1 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -78,11 +78,14 @@ hangupCalls(Call::SubcallSet callptr_list, int errcode)
 
 //==============================================================================
 
-Call::Call(Account& account, const std::string& id, Call::CallType type)
+Call::Call(Account& account, const std::string& id, Call::CallType type,
+           const std::map<std::string, std::string>& details)
     : id_(id)
     , type_(type)
     , account_(account)
 {
+    setEarlyDetails(details);
+
     addStateListener([this](UNUSED Call::CallState call_state,
                             UNUSED Call::ConnectionState cnx_state,
                             UNUSED int code) {
@@ -308,6 +311,12 @@ Call::toggleRecording()
     return startRecording;
 }
 
+void
+Call::setEarlyDetails(const std::map<std::string, std::string>& details)
+{
+    (void)details;
+}
+
 std::map<std::string, std::string>
 Call::getDetails() const
 {
diff --git a/src/call.h b/src/call.h
index 1caf770951..7d0d2f16b8 100644
--- a/src/call.h
+++ b/src/call.h
@@ -311,8 +311,10 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
          * Constructor of a call
          * @param id Unique identifier of the call
          * @param type set definitely this call as incoming/outgoing
+         * @param details volatile details to customize the call creation
          */
-        Call(Account& account, const std::string& id, Call::CallType type);
+        Call(Account& account, const std::string& id, Call::CallType type,
+             const std::map<std::string, std::string>& details = {});
 
         // TODO all these members are not protected against multi-thread access
 
@@ -333,6 +335,8 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
     private:
         friend void hangupCallsIf(Call::SubcallSet, int, const std::function<bool(Call*)>&);
 
+        void setEarlyDetails(const std::map<std::string, std::string>& details);
+
         bool validStateTransition(CallState newState);
 
         void checkPendingIM();
diff --git a/src/call_factory.h b/src/call_factory.h
index 8a3e72fab7..019a87b4c5 100644
--- a/src/call_factory.h
+++ b/src/call_factory.h
@@ -71,7 +71,8 @@ class CallFactory {
          * @param account account useed to create this call
          */
         template <class T, class A>
-        std::shared_ptr<T> newCall(A& account, const std::string& id, Call::CallType type) {
+        std::shared_ptr<T> newCall(A& account, const std::string& id, Call::CallType type,
+                                   const std::map<std::string, std::string>& details={}) {
             if (!allowNewCall_) {
                 RING_WARN("newCall aborted : CallFactory in forbid state");
                 return nullptr;
@@ -81,8 +82,9 @@ class CallFactory {
             // and not accessible from std::make_shared.
             // We use a concrete class to bypass this restriction.
             struct ConcreteCall : T {
-                    ConcreteCall(A& account, const std::string& id, Call::CallType type)
-                        : T(account, id, type) {}
+                    ConcreteCall(A& account, const std::string& id, Call::CallType type,
+                                 const std::map<std::string, std::string>& details)
+                        : T(account, id, type, details) {}
             };
 
             if (hasCall(id)) {
@@ -90,7 +92,7 @@ class CallFactory {
                 return nullptr;
             }
 
-            auto call = std::make_shared<ConcreteCall>(account, id, type);
+            auto call = std::make_shared<ConcreteCall>(account, id, type, details);
             if (call) {
                 std::lock_guard<std::recursive_mutex> lk(callMapsMutex_);
                 callMaps_[call->getLinkType()].insert(std::make_pair(id, call));
diff --git a/src/client/callmanager.cpp b/src/client/callmanager.cpp
index b0d43b82a3..28dfd67fca 100644
--- a/src/client/callmanager.cpp
+++ b/src/client/callmanager.cpp
@@ -65,6 +65,18 @@ placeCall(const std::string& accountID, const std::string& to)
     }
 }
 
+std::string
+placeCall(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& volatileCallDetails)
+{
+    // Check if a destination number is available
+    if (to.empty()) {
+        RING_DBG("No number entered - Call stopped");
+        return {};
+    } else {
+        return ring::Manager::instance().outgoingCall(accountID, to, "", volatileCallDetails);
+    }
+}
+
 bool
 refuse(const std::string& callID)
 {
diff --git a/src/dring/callmanager_interface.h b/src/dring/callmanager_interface.h
index 2b6a549997..5ddbc669e7 100644
--- a/src/dring/callmanager_interface.h
+++ b/src/dring/callmanager_interface.h
@@ -37,6 +37,7 @@ void registerCallHandlers(const std::map<std::string, std::shared_ptr<CallbackWr
 
 /* Call related methods */
 std::string placeCall(const std::string& accountID, const std::string& to);
+std::string placeCall(const std::string& accountID, const std::string& to, const std::map<std::string, std::string>& VolatileCallDetails);
 
 bool refuse(const std::string& callID);
 bool accept(const std::string& callID);
diff --git a/src/manager.cpp b/src/manager.cpp
index 9939a087da..f74a26dd38 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -843,7 +843,8 @@ Manager::unregisterAccounts()
 std::string
 Manager::outgoingCall(const std::string& preferred_account_id,
                           const std::string& to,
-                          const std::string& conf_id)
+                          const std::string& conf_id,
+                          const std::map<std::string, std::string>& volatileCallDetails)
 {
     if (not conf_id.empty() and not isConference(conf_id)) {
         RING_ERR("outgoingCall() failed, invalid conference id");
@@ -859,7 +860,7 @@ Manager::outgoingCall(const std::string& preferred_account_id,
          * as the factory may decide to use another account (like IP2IP).
          */
         RING_DBG("New outgoing call to %s", to_cleaned.c_str());
-        call = newOutgoingCall(to_cleaned, preferred_account_id);
+        call = newOutgoingCall(to_cleaned, preferred_account_id, volatileCallDetails);
     } catch (const std::exception &e) {
         RING_ERR("%s", e.what());
         return {};
@@ -3009,7 +3010,9 @@ Manager::getAudioDriver()
 }
 
 std::shared_ptr<Call>
-Manager::newOutgoingCall(const std::string& toUrl, const std::string& preferredAccountId)
+Manager::newOutgoingCall(const std::string& toUrl,
+                         const std::string& preferredAccountId,
+                         const std::map<std::string, std::string>& volatileCallDetails)
 {
     auto account = getAccount(preferredAccountId);
     if (account and !account->isUsable()) {
@@ -3042,7 +3045,7 @@ Manager::newOutgoingCall(const std::string& toUrl, const std::string& preferredA
         return nullptr;
     }
 
-    return account->newOutgoingCall(toUrl);
+    return account->newOutgoingCall(toUrl, volatileCallDetails);
 }
 
 #ifdef RING_VIDEO
diff --git a/src/manager.h b/src/manager.h
index ec05c50cbd..f28a641ea9 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -119,14 +119,15 @@ class Manager {
         /**
          * Functions which occur with a user's action
          * Place a new call
-         * @param accountId	The account to make the call with
+         * @param accountId The account to make the call with
          * @param to  The recipient of the call
          * @param conf_id The conference identifier if any
          * @return id The call ID on success, empty string otherwise
          */
         std::string outgoingCall(const std::string& accountId,
                                  const std::string& to,
-                                 const std::string& conf_id = "");
+                                 const std::string& conf_id = "",
+                                 const std::map<std::string, std::string>& volatileCallDetails = {});
 
         /**
          * Functions which occur with a user's action
@@ -365,7 +366,7 @@ class Manager {
 
         /**
          * Notify the client he has voice mails
-         * @param accountId	  The account identifier
+         * @param accountId   The account identifier
          * @param nb_msg The number of messages
          */
         void startVoiceMessageNotification(const std::string& accountId, int nb_msg);
@@ -397,7 +398,7 @@ class Manager {
 
         /**
          * Retrieve details about a given account
-         * @param accountID	  The account identifier
+         * @param accountID   The account identifier
          * @return std::map< std::string, std::string > The account details
          */
         std::map<std::string, std::string> getAccountDetails(const std::string& accountID) const;
@@ -411,7 +412,7 @@ class Manager {
 
         /**
          * Retrieve details about a given call
-         * @param callID	  The account identifier
+         * @param callID      The account identifier
          * @return std::map< std::string, std::string > The call details
          */
         std::map<std::string, std::string> getCallDetails(const std::string& callID);
@@ -424,7 +425,7 @@ class Manager {
 
         /**
          * Retrieve details about a given call
-         * @param callID	  The account identifier
+         * @param callID      The account identifier
          * @return std::map< std::string, std::string > The call details
          */
         std::map<std::string, std::string> getConferenceDetails(const std::string& callID) const;
@@ -454,8 +455,8 @@ class Manager {
          * Save the details of an existing account, given the account ID
          * This will load the configuration map with the given data.
          * It will also register/unregister links where the 'Enabled' switched.
-         * @param accountID	  The account identifier
-         * @param details	  The account parameters
+         * @param accountID   The account identifier
+         * @param details     The account parameters
          */
         void setAccountDetails(const std::string& accountID,
                                const std::map<std::string, ::std::string > &details);
@@ -483,7 +484,7 @@ class Manager {
          * Delete an existing account, unregister VoIPLink associated, and
          * purge from configuration.
          * If 'flush' argument is true, filesystem entries are also removed.
-         * @param accountID	The account unique ID
+         * @param accountID The account unique ID
          */
         void removeAccount(const std::string& accountID, bool flush=false);
 
@@ -554,8 +555,8 @@ class Manager {
         /**
          * Ringtone option.
          * If ringtone is enabled, ringtone on incoming call use custom choice. If not, only standart tone.
-         * @return int	1 if enabled
-         *	        0 otherwise
+         * @return int  1 if enabled
+         *          0 otherwise
          */
         int isRingtoneEnabled(const std::string& id);
 
@@ -618,8 +619,8 @@ class Manager {
         /**
          * Get the audio manager
          * @return int The audio manager
-         *		    "alsa"
-         *		    "pulseaudio"
+         *          "alsa"
+         *          "pulseaudio"
          */
         std::string getAudioManager() const;
 
@@ -707,7 +708,7 @@ class Manager {
 
         /**
          * Get the current call id
-         * @return std::string	The call id or ""
+         * @return std::string  The call id or ""
          */
         const std::string getCurrentCallId() const;
 
@@ -830,7 +831,8 @@ class Manager {
          * @note This function raises VoipLinkException() on errors.
          */
         std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl,
-                                              const std::string& preferredAccountId);
+                                              const std::string& preferredAccountId,
+                                              const std::map<std::string, std::string>& volatileCallDetails = {});
 
         CallFactory callFactory;
 
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 65c1106e76..e9b19042dd 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -329,13 +329,14 @@ RingAccount::newIncomingCall(const std::string& from)
 
 template <>
 std::shared_ptr<SIPCall>
-RingAccount::newOutgoingCall(const std::string& toUrl)
+RingAccount::newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails)
 {
     auto sufix = stripPrefix(toUrl);
     RING_DBG("Calling DHT peer %s", sufix.c_str());
     auto& manager = Manager::instance();
     auto call = manager.callFactory.newCall<SIPCall, RingAccount>(*this, manager.getNewCallID(),
-                                                                  Call::CallType::OUTGOING);
+                                                                  Call::CallType::OUTGOING,
+                                                                  volatileCallDetails);
 
     call->setIPToIP(true);
     call->setSecure(isTlsEnabled());
@@ -395,7 +396,8 @@ RingAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
 
         auto& manager = Manager::instance();
         auto dev_call = manager.callFactory.newCall<SIPCall, RingAccount>(*sthis, manager.getNewCallID(),
-                                                                          Call::CallType::OUTGOING);
+                                                                          Call::CallType::OUTGOING,
+                                                                          call->getDetails());
         std::weak_ptr<SIPCall> weak_dev_call = dev_call;
         dev_call->setIPToIP(true);
         dev_call->setSecure(sthis->isTlsEnabled());
@@ -533,9 +535,9 @@ RingAccount::onConnectedOutgoingCall(SIPCall& call, const std::string& to_id, Ip
 }
 
 std::shared_ptr<Call>
-RingAccount::newOutgoingCall(const std::string& toUrl)
+RingAccount::newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails)
 {
-    return newOutgoingCall<SIPCall>(toUrl);
+    return newOutgoingCall<SIPCall>(toUrl, volatileCallDetails);
 }
 
 bool
diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h
index e0769f889e..27b65e1679 100644
--- a/src/ringdht/ringaccount.h
+++ b/src/ringdht/ringaccount.h
@@ -215,7 +215,8 @@ class RingAccount : public SIPAccountBase {
          * Implementation of Account::newOutgoingCall()
          * Note: keep declaration before newOutgoingCall template.
          */
-        std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl) override;
+        std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl,
+                                              const std::map<std::string, std::string>& volatileCallDetails = {}) override;
 
         /**
          * Create outgoing SIPCall.
@@ -227,11 +228,11 @@ class RingAccount : public SIPAccountBase {
 #ifndef RING_UWP
         template <class T=SIPCall>
         std::shared_ptr<enable_if_base_of<T, SIPCall> >
-        newOutgoingCall(const std::string& toUrl);
+        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
 #else
         template <class T>
         std::shared_ptr<T>
-        newOutgoingCall(const std::string& toUrl);
+        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
 #endif
 
         /**
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 77d883e546..caf6a87caf 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -164,13 +164,15 @@ SIPAccount::newIncomingCall(const std::string& from UNUSED)
 
 template <>
 std::shared_ptr<SIPCall>
-SIPAccount::newOutgoingCall(const std::string& toUrl)
+SIPAccount::newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails)
 {
     std::string to;
     int family;
 
     auto& manager = Manager::instance();
-    auto call = manager.callFactory.newCall<SIPCall, SIPAccount>(*this, manager.getNewCallID(), Call::CallType::OUTGOING);
+    auto call = manager.callFactory.newCall<SIPCall, SIPAccount>(*this, manager.getNewCallID(),
+                                                                 Call::CallType::OUTGOING,
+                                                                 volatileCallDetails);
     call->setSecure(isTlsEnabled());
 
     if (isIP2IP()) {
@@ -308,9 +310,9 @@ SIPAccount::getTransportSelector() {
 }
 
 std::shared_ptr<Call>
-SIPAccount::newOutgoingCall(const std::string& toUrl)
+SIPAccount::newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails)
 {
-    return newOutgoingCall<SIPCall>(toUrl);
+    return newOutgoingCall<SIPCall>(toUrl, volatileCallDetails);
 }
 
 bool
diff --git a/src/sip/sipaccount.h b/src/sip/sipaccount.h
index d8a311eaf6..8a6cecdb82 100644
--- a/src/sip/sipaccount.h
+++ b/src/sip/sipaccount.h
@@ -455,7 +455,8 @@ class SIPAccount : public SIPAccountBase {
          * Implementation of Account::newOutgoingCall()
          * Note: keep declaration before newOutgoingCall template.
          */
-        std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl) override;
+        std::shared_ptr<Call> newOutgoingCall(const std::string& toUrl,
+                                              const std::map<std::string, std::string>& volatileCallDetails = {}) override;
 
         /**
          * Create outgoing SIPCall.
@@ -467,11 +468,11 @@ class SIPAccount : public SIPAccountBase {
 #ifndef RING_UWP
         template <class T=SIPCall>
         std::shared_ptr<enable_if_base_of<T, SIPCall> >
-        newOutgoingCall(const std::string& toUrl);
+        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
 #else
         template <class T>
         std::shared_ptr<T>
-        newOutgoingCall(const std::string& toUrl);
+        newOutgoingCall(const std::string& toUrl, const std::map<std::string, std::string>& volatileCallDetails = {});
 #endif
 
         /**
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 70b625bf7e..776e023963 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -108,8 +108,9 @@ dtmfSend(SIPCall &call, char code, const std::string &dtmf)
     call.sendSIPInfo(dtmf_body, "dtmf-relay");
 }
 
-SIPCall::SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType type)
-    : Call(account, id, type)
+SIPCall::SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType type,
+                 const std::map<std::string, std::string>& details)
+    : Call(account, id, type, details)
     , avformatrtp_(new AudioRtpSession(id))
 #ifdef RING_VIDEO
     // The ID is used to associate video streams to calls
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index 9d39d9172b..2f57e01d72 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -80,7 +80,8 @@ protected:
      * @param id    The call identifier
      * @param type  The type of the call. Could be Incoming or Outgoing
      */
-    SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType type);
+    SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType type,
+            const std::map<std::string, std::string>& details={});
 
 public: // overridden
     const char* getLinkType() const override {
-- 
GitLab