X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fvicar-daemon%2Fsrc%2Fcallrouter.cpp;fp=src%2Fvicar-daemon%2Fsrc%2Fcallrouter.cpp;h=9313b2feb09be927376fcfb37dd3cac9fbf2ea83;hb=11d5c26f3a622a0fc32f9cb89e1658846201af4d;hp=e6155f5f48b7561901884174dd242f52c0396013;hpb=40b1207a3eb33b54e8ac780cabd4a68f7931f248;p=vicar diff --git a/src/vicar-daemon/src/callrouter.cpp b/src/vicar-daemon/src/callrouter.cpp old mode 100644 new mode 100755 index e6155f5..9313b2f --- a/src/vicar-daemon/src/callrouter.cpp +++ b/src/vicar-daemon/src/callrouter.cpp @@ -1,265 +1,168 @@ /* -@version: 0.2 -@author: Sudheer K. +@version: 0.5 +@author: Sudheer K. @license: GNU General Public License */ #include "callrouter.h" +#include "vicardbusadaptor.h" #include #include +#include +#include #include #include #include -#include +#include #include -//Create a statis Dbus utility object that will be shared across all member functions -static DbusUtility dbusUtility = DbusUtility(); -static QString strLastDialedNumber = QString(); + +//static QString strLastDialedNumber = QString(); +//static org::maemo::vicar::Profile currentProfile; + +class CallRouterPrivate +{ +public: + CallRouterPrivate(CallRouter * p) : + databaseUtility(new DatabaseUtility(p)), + dbusAdaptor(new VicarDbusAdaptor(p)), + dbusUtility(new DbusUtility(p)), + gconfUtility(new GConfUtility(p)), + tpUtility(new TelepathyUtility(p)), + parent(p) + { + Q_ASSERT(0 != dbusAdaptor); + //Do not open here - Unable to capture changes to DB if it is open too early and closed late. + //databaseUtility->openDatabase(); + } + + ~CallRouterPrivate() + { + qDebug() << "VICaR: Call Router Destructing"; + //databaseUtility->closeDatabase(); + } + + DatabaseUtility *databaseUtility; + VicarDbusAdaptor * dbusAdaptor; + DbusUtility * dbusUtility; + GConfUtility * gconfUtility; + TelepathyUtility *tpUtility; + QString strLastDialedNumber; + org::maemo::vicar::Profile *currentProfile; + CallRouter * const parent; +}; + +// --------------------------------------------------------------------------- CallRouter::CallRouter(QObject *parent) : - QObject(parent) + QObject(parent), + d(new CallRouterPrivate(this)) { - gconfUtility = new GConfUtility(); + Q_ASSERT(0 != d); + this->registerDBusService(); + qDebug() << "Registered DBus Service " << APPLICATION_DBUS_SERVICE; } CallRouter::~CallRouter(){ - delete gconfUtility; - gconfUtility = 0; } void CallRouter::registerDBusService(){ - QDBusConnection connection = dbusUtility.getConnection(); + //Connect to Session Bus + QDBusConnection connection = d->dbusUtility->getConnection(false); + + if (!connection.interface()->isServiceRegistered(APPLICATION_DBUS_SERVICE)){ - if (!connection.registerService(APPLICATION_DBUS_SERVICE)) { - qDebug() << dbusUtility.getErrorMessage(); - exit(1); + if (!connection.registerService(APPLICATION_DBUS_SERVICE)) { + qDebug() << d->dbusUtility->getErrorMessage(); + exit(1); + } } - if (!connection.registerObject(APPLICATION_DBUS_PATH, this, - QDBusConnection::ExportScriptableSlots)) { - qDebug() << dbusUtility.getErrorMessage(); + if (!connection.registerObject(APPLICATION_DBUS_PATH, this, QDBusConnection::ExportAdaptors)) { + qDebug() << d->dbusUtility->getErrorMessage(); exit(2); } - this->connectToDBusSignals(); - } void CallRouter::unregisterDBusService(){ - this->disconnectFromDBusSignals(); - - QDBusConnection connection = dbusUtility.getConnection(); + //Disconnect from Session bus + QDBusConnection connection = d->dbusUtility->getConnection(false); connection.unregisterObject(APPLICATION_DBUS_PATH,QDBusConnection::UnregisterTree); if (!connection.unregisterService(APPLICATION_DBUS_SERVICE)) { - qDebug() << dbusUtility.getErrorMessage(); + qDebug() << d->dbusUtility->getErrorMessage(); exit(3); } } -void CallRouter::connectToDBusSignals(){ +QString CallRouter::callViaCallingCard(QString strDestinationNumber){ - QDBusConnection connection = dbusUtility.getConnection(); + d->currentProfile = new org::maemo::vicar::Profile(); + d->currentProfile->profileID = 0; - // Connect to the signal to enable call routing - bool success = connection.connect(QString(""),QString(""), - APPLICATION_DBUS_INTERFACE, - QString("startOutgoingCallMonitor"),this, - SLOT(startOutgoingCallMonitor())); - - if (success){ - qDebug() << "Successfully connected to Dbus signal org.maemo.vicar.startOutgoingCallMonitor"; - } - else{ - qDebug() << "Failed to connect to Dbus signal org.maemo.vicar.startOutgoingCallMonitor"; - qDebug() <<"DBus Error: "<< qPrintable(dbusUtility.getErrorMessage()); - } - - // Connect to the signal to disable call routing - success = connection.connect(QString(""),QString(""), - APPLICATION_DBUS_INTERFACE, - QString("stopOutgoingCallMonitor"),this, - SLOT(stopOutgoingCallMonitor())); - - if (success){ - qDebug() << "Successfully connected to Dbus signal org.maemo.vicar.stopOutgoingCallMonitor"; - } - else{ - qDebug() << "Failed to connect to Dbus signal org.maemo.vicar.stopOutgoingCallMonitor"; - qDebug() <<"DBus Error: "<< qPrintable(dbusUtility.getErrorMessage()); - } - -} + d->databaseUtility->openDatabase(); + bool result = d->databaseUtility->findProfileByNumber(strDestinationNumber,d->currentProfile); -void CallRouter::disconnectFromDBusSignals(){ - - QDBusConnection connection = dbusUtility.getConnection(); - - // Disconnect from the signal to enable call routing - bool success = connection.disconnect(QString(""),QString(""), - APPLICATION_DBUS_INTERFACE, - QString("startOutgoingCallMonitor"),this, - SLOT(startOutgoingCallMonitor())); - - if (success){ - qDebug() << "Successfully disconnected from Dbus signal org.maemo.vicar.startOutgoingCallMonitor"; - } - else{ - qDebug() << "Failed to disconnect from Dbus signal org.maemo.vicar.startOutgoingCallMonitor"; - qDebug() <<"DBus Error: "<< qPrintable(dbusUtility.getErrorMessage()); - } - - // Disconnect from the signal to disable call routing - success = connection.connect(QString(""),QString(""), - APPLICATION_DBUS_INTERFACE, - QString("stopOutgoingCallMonitor"),this, - SLOT(stopOutgoingCallMonitor())); - - if (success){ - qDebug() << "Successfully disconnected from Dbus signal org.maemo.vicar.stopOutgoingCallMonitor"; - } - else{ - qDebug() << "Failed to disconnect from Dbus signal org.maemo.vicar.stopOutgoingCallMonitor"; - qDebug() <<"DBus Error: "<< qPrintable(dbusUtility.getErrorMessage()); - } - -} - -void CallRouter::startOutgoingCallMonitor(){ - - // Connect to DBus to monitor all outgoing calls - - QDBusConnection connection = dbusUtility.getConnection(); - - - // Declare the slot to be executed when new calls are placed - - bool success = connection.connect(QString(""), - CSD_CALL_PATH, - CSD_CALL_INTERFACE, - QString("CreateRequested"),this, - SLOT(processOutgoingCall(const QDBusMessage&))); - - if (success){ - qDebug() << "Successfully connected to Dbus signal CreateRequested in interface "<< CSD_CALL_INTERFACE; - } - else{ - qDebug() << "Failed to connect to Dbus signal CreateRequested in interface " << CSD_CALL_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); - } - - -} - -void CallRouter::stopOutgoingCallMonitor(){ - - this->stopCallStatusMonitors(); - - //Disconnect the slots from Dbus signals - QDBusConnection connection = dbusUtility.getConnection(); - - // Disconnect the slot for new calls - bool status = connection.disconnect(QString(""), - CSD_CALL_PATH, - CSD_CALL_INTERFACE, - QString("CreateRequested"),this, - SLOT(processOutgoingCall(const QDBusMessage&))); - - if (status){ - qDebug() << "Successfully disconnected from Dbus signal CreateRequested in interface "<< CSD_CALL_INTERFACE; - } - else{ - qDebug() << "Failed to disconnect from Dbus signal CreateRequested in interface "<< CSD_CALL_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); - } - -} - -void CallRouter::processOutgoingCall(const QDBusMessage& dbusMessage){ - - //Verify Whether Call Routing is Enabled - bool isRoutingEnabled = gconfUtility->getGconfValueBoolean("routing_enabled"); - - if (isRoutingEnabled){ - //User is making a phone call. Get the phone number and verify if it is an international number - QList listArguments = dbusMessage.arguments(); - QString strInternationalNumber = listArguments.first().toString(); - - qDebug() << "New Call Identified. Destination number is " << strInternationalNumber; - - if (strInternationalNumber.startsWith("+") || - strInternationalNumber.startsWith("00")) - { - qDebug() << "International number "<< strInternationalNumber << " recognized. Starting proceedings.."; - - //Check whether this is one of the excluded country codes - if (!isExcludedNumber(strInternationalNumber)){ - - //International number. Disconnect the current call (A new call will be placed) - - //No arguments required to cancel the current call - QList argsToSend; - bool status = dbusUtility.sendMethodCall(CSD_CALL_SERVICE, - CSD_CALL_PATH, - CSD_CALL_INTERFACE, - QString("Release"),argsToSend); - - QString strUserMessage; - if (status){ - strUserMessage = QString("Routing international call via ").append(APPLICATION_FRIENDLY_NAME).append(".."); - qDebug() << strUserMessage; - strLastDialedNumber = strInternationalNumber; - } - else{ - strUserMessage = QString("Call could not be cancelled."); - qDebug() << dbusUtility.getErrorMessage(); - } - - dbusUtility.displayNotification(strUserMessage); - - //Wait for a few seconds before the current call is completely disconnected - QTimer *timer = new QTimer(this); - timer->setSingleShot(true); - connect(timer, SIGNAL(timeout()), this, SLOT(callViaCallingCard())); - timer->start(3000); - } + QString strErrorMessage; + if (!result){ + strErrorMessage = QString("Error finding VICaR profile. %1").arg(d->databaseUtility->lastError().text()); } - } -} - -void CallRouter::callViaCallingCard(){ - //Now call the calling card number. This is generally a local and/or tollfree number + else if (d->currentProfile->profileID == 0){ + bool routeOnDefault = d->gconfUtility->getGconfValueBoolean("route_on_default"); + if (routeOnDefault){ + qDebug() << "Routing directly as per configuration"; + this->placeCall(strDestinationNumber); + } + else{ + qDebug() << "No profile found. Stopping.."; + strErrorMessage = "VICaR: No routing profile defined for this number."; + d->dbusUtility->displayNotification(strErrorMessage ); + } + } + else{ + //Now call the calling card number. This is generally a local and/or tollfree number + QString strCallingCardNumber = d->currentProfile->gatewayNumber; + qDebug() << "Initiating call to "<< strCallingCardNumber; + bool status = this->placeCall(strCallingCardNumber); + d->strLastDialedNumber = strDestinationNumber; - QString strCallingCardNumber = gconfUtility->getGconfValueString("calling_card_number"); + QString strUserMessage; - qDebug() << "Wait time elapsed. Initiating call to "<< strCallingCardNumber; + if (status){ + qDebug() << "Call initiated successfully. Connecting DBus slot for audio connection monitor"; + startCallStatusMonitors(); + } + else { + strUserMessage = QString("Unable to initiate new call to ").append(strCallingCardNumber); + strErrorMessage = d->dbusUtility->getErrorMessage(); + qDebug() << strErrorMessage; + d->strLastDialedNumber.clear(); + delete d->currentProfile; + d->currentProfile = 0; + } + d->dbusUtility->displayNotification(strUserMessage); + } - QList argsToSend; - argsToSend.append(strCallingCardNumber); - argsToSend.append(0); + d->databaseUtility->closeDatabase(); + return strErrorMessage; +} - bool status = dbusUtility.sendMethodCall(CSD_SERVICE, - CSD_CALL_PATH, - CSD_CALL_INTERFACE, - QString("CreateWith"),argsToSend); +bool CallRouter::placeCall(QString number){ - QString strUserMessage; - if (status){ - qDebug() << "Call initiated successfully. Connecting DBus slot for audio connection monitor"; - startCallStatusMonitors(); - } - else { - strUserMessage = QString("Unable to initiate new call to ").append(strCallingCardNumber); - qDebug() << dbusUtility.getErrorMessage(); - strLastDialedNumber.clear(); - } + QList argsToSend; + argsToSend.append(number); + argsToSend.append(0); - dbusUtility.displayNotification(strUserMessage); + bool status = d->dbusUtility->sendMethodCall(CSD_SERVICE, + CSD_CALL_PATH, + CSD_CALL_INTERFACE, + QString("CreateWith"),argsToSend); + return status; } @@ -268,7 +171,7 @@ void CallRouter::startCallStatusMonitors(){ We need this to confirm whether a call went though successfully. */ - QDBusConnection connection = dbusUtility.getConnection(); + QDBusConnection connection = d->dbusUtility->getConnection(); bool success = connection.connect(QString(""), CSD_CALL_INSTANCE_PATH, @@ -281,7 +184,7 @@ void CallRouter::startCallStatusMonitors(){ } else{ qDebug() << "Failed to connect to Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } /* Declare the slot to be executed when the call is terminated (due to connection errors etc). @@ -299,7 +202,7 @@ void CallRouter::startCallStatusMonitors(){ } else{ qDebug() << "Failed to connect to Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } /* Declare the slot to be executed when a call is received @@ -322,15 +225,17 @@ void CallRouter::startCallStatusMonitors(){ } else{ qDebug() << "Failed to connect to Dbus signal Coming in interface" << CSD_CALL_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } } void CallRouter::stopCallStatusMonitors(){ - strLastDialedNumber.clear(); + d->strLastDialedNumber.clear(); + delete d->currentProfile; + d->currentProfile = 0; - QDBusConnection connection = dbusUtility.getConnection(); + QDBusConnection connection = d->dbusUtility->getConnection(); // Disconnect the slot for audio connection status bool status = connection.disconnect(QString(""), @@ -344,7 +249,7 @@ void CallRouter::stopCallStatusMonitors(){ } else{ qDebug() << "Failed to disconnect from Dbus signal AudioConnect in interface "<< CSD_CALL_INSTANCE_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } // Disconnect the slot for monitoring terminated calls @@ -359,7 +264,7 @@ void CallRouter::stopCallStatusMonitors(){ } else{ qDebug() << "Failed to disconnect from Dbus signal Terminated in interface "<< CSD_CALL_INSTANCE_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } // Disconnect the slot for monitoring incoming calls @@ -374,13 +279,13 @@ void CallRouter::stopCallStatusMonitors(){ } else{ qDebug() << "Failed to disconnect from Dbus signal Coming in interface" << CSD_CALL_INTERFACE; - qDebug() <<"DBus Error: "<< dbusUtility.getErrorMessage(); + qDebug() <<"DBus Error: "<< d->dbusUtility->getErrorMessage(); } } void CallRouter::sendNumberAsDTMFCode(const QDBusMessage& dbusMessage){ - if (!strLastDialedNumber.isEmpty()){ + if (!d->strLastDialedNumber.isEmpty() && d->currentProfile != 0){ //Verify whether we have the last dialed number available QList listArguments = dbusMessage.arguments(); @@ -388,14 +293,14 @@ void CallRouter::sendNumberAsDTMFCode(const QDBusMessage& dbusMessage){ if (audioConnected){ // Now that the call to Calling card number is successful. We can send the original number as DTMF tones - QString strDTMFCode = convertToDTMFCode(strLastDialedNumber); + QString strDTMFCode = convertToDTMFCode(d->strLastDialedNumber); qDebug() << "Audio connection established. Sending DTMF code "<< strDTMFCode; QList argsToSend; argsToSend.append(strDTMFCode); - bool status = dbusUtility.sendMethodCall(CSD_SERVICE, + bool status = d->dbusUtility->sendMethodCall(CSD_SERVICE, CSD_CALL_PATH, CSD_CALL_INTERFACE, QString("SendDTMF"),argsToSend); @@ -403,7 +308,7 @@ void CallRouter::sendNumberAsDTMFCode(const QDBusMessage& dbusMessage){ if (status){ QString strMessage = strDTMFCode.append(" sent as DTMF code"); qDebug() << strMessage; - dbusUtility.displayNotification(strMessage); + d->dbusUtility->displayNotification(strMessage); } else{ qDebug() << "Unable to send DTMF code."; @@ -419,6 +324,9 @@ void CallRouter::sendNumberAsDTMFCode(const QDBusMessage& dbusMessage){ qDebug() << "Now disconnecting from call status monitors.."; stopCallStatusMonitors(); + d->strLastDialedNumber.clear(); + delete d->currentProfile; + d->currentProfile = 0; } else{ qDebug() << "Audio not yet connected."; @@ -434,16 +342,21 @@ QString CallRouter::convertToDTMFCode(QString strNumber){ QString strDTMFCode; if (!strNumber.isEmpty()){ + int intDTMFDelay = 1; - //Get the format required by calling card from coniguration - QString qstrDTMFFormat = gconfUtility->getGconfValueString("dtmf_format"); - int intDTMFDelay = gconfUtility->getGconfValueInteger("dtmf_delay"); + //Add the prefix p so that there is some delay after the call is picked up by the automated system to send DTMF tones. + strDTMFCode = QString("").fill('p',intDTMFDelay); - if (intDTMFDelay <1 ) intDTMFDelay = 1; - if (qstrDTMFFormat.isEmpty()) qstrDTMFFormat = ""; + //Now check whether we need a prefix + QString strDTMFPrefix = d->currentProfile->dtmfPrefix; - //Add the prefix p so that there is some delay after the call is picked up by the automated system to send DTMF tones. - strDTMFCode = QString("").fill('p',intDTMFDelay); + if (!strDTMFPrefix.isEmpty()){ + strDTMFCode = strDTMFCode.append(strDTMFPrefix); + } + + //Get the format required by calling card from coniguration + QString qstrDTMFFormat = d->currentProfile->dtmfFormat; + if (qstrDTMFFormat.isEmpty()) qstrDTMFFormat = ""; /* Replace 00 (international dialing code) at the beginning and also replace any character other than the numbers 0-9 and p. @@ -463,13 +376,12 @@ QString CallRouter::convertToDTMFCode(QString strNumber){ else if (qstrDTMFFormat.startsWith("011")){ strDTMFCode = strDTMFCode.append("011"); } - //Default case - we don't need any prefix strDTMFCode = strDTMFCode.append(strNumber); //Now check whether we need a suffix - QString strDTMFSuffix = gconfUtility->getGconfValueString("dtmf_suffix"); - if (!strDTMFSuffix.isEmpty() && !strDTMFSuffix.contains("--None--")){ + QString strDTMFSuffix = d->currentProfile->dtmfSuffix; + if (!strDTMFSuffix.isEmpty()){ strDTMFCode = strDTMFCode.append(strDTMFSuffix); } } @@ -477,24 +389,33 @@ QString CallRouter::convertToDTMFCode(QString strNumber){ return strDTMFCode; } -bool CallRouter::isExcludedNumber(QString strInternationalNumber){ +//DBus Method used by external applications to check whether VICaR is enabled and running +bool CallRouter::isRunning(){ - bool isExcluded = false; + return true; - //Get the list of excluded codes - QString qstrExcludedNumbers = gconfUtility->getGconfValueString("numbers_to_exclude"); - QStringList strExcludedCodeList = qstrExcludedNumbers.split(","); - QStringListIterator iterator(strExcludedCodeList); + //Verify Whether VICaR telepathy account is online + /* + if (d->tpUtility->getAccountStatus() == "Connected"){ + return true; + } + else{ + return false; + } + */ +} - QRegExp regexp = QRegExp("(^0{2})|[^0-9p]"); +//DBus Method used by external applications to call via VICaR +QString CallRouter::callInternationalNumber(const QString& strDestinationNumber){ - while (iterator.hasNext()){ - QString strCode = iterator.next(); - strCode = strCode.replace(regexp,""); - strInternationalNumber = strInternationalNumber.replace(regexp,""); - if (!strCode.isEmpty() && strInternationalNumber.startsWith(strCode)){ - isExcluded = true; - } + qDebug() << "New call requested by external application. Destination number is " << strDestinationNumber; + QString strErrorMessage = this->callViaCallingCard(strDestinationNumber); + qDebug() << strErrorMessage; + + if (strErrorMessage.isEmpty()){ + return QString("Success"); } - return isExcluded; -} + else{ + return strErrorMessage; + } + }