Commit c8c0c7e2 authored by Nicolas Jager's avatar Nicolas Jager Committed by Guillaume Roguez

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's avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 64d25ed8
......@@ -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.
......
......@@ -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))
{
......
......@@ -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);
......
......@@ -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$])
......
......@@ -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
......
......@@ -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={});
......
......@@ -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
{
......
......@@ -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();
......
......@@ -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));
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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
/**
......
......@@ -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
......
......@@ -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
/**
......
......@@ -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
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment