X-Git-Url: http://git.maemo.org/git/?p=jenirok;a=blobdiff_plain;f=src%2Fdaemon%2Fcalllistener.cpp;h=c76cfdc6958a300637c8b6c14b229ee2a10ffd22;hp=9071713375fcaa78f63d9dad4bd4a609b23298ad;hb=d93782e7a5ae0fc072d094fd645cf415a34a2244;hpb=cf883c1283eb6b096592ef875a32696fee9dd6ff diff --git a/src/daemon/calllistener.cpp b/src/daemon/calllistener.cpp index 9071713..c76cfdc 100644 --- a/src/daemon/calllistener.cpp +++ b/src/daemon/calllistener.cpp @@ -17,9 +17,14 @@ */ #include -#include +#include +#include #include "calllistener.h" #include "settings.h" +#include "cache.h" +#include "contactmanager.h" +#include "connectionmanager.h" +#include "sourcecoreconfig.h" #include "db.h" namespace @@ -31,21 +36,38 @@ namespace const QString CALL_SIGNAL_INCOMING = "Coming"; const QString CALL_SIGNAL_RELEASE = "Release"; const QString CALL_SIGNAL_TERMINATED = "Terminated"; + const QString CALL_SIGNAL_ANSWERED = "AudioConnect"; } QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus(); -CallListener::CallListener(): eniro_(0), contactManager_(0), box_(0), label_(0) +CallListener::CallListener(): source_(0), +closeConnection_(false), initialized_(false), box_(0), label_(0), +retries_(-1), timer_(0), currentCall_(0) { } CallListener::~CallListener() { end(); + DB::removeDatabase(); } -void CallListener::begin() +bool CallListener::begin() { + if(Settings::instance()->getConnectionType() == Settings::ALWAYS_ASK) + { + qDebug() << "Bad connection settings, unable to start"; + return false; + } + + sourceId_ = Source::stringToId(Settings::instance()->get("source")); + QMap tmpConfig; + SourceCoreConfig* config = SourceCoreConfig::getCoreConfig(sourceId_); + config->getConfig(tmpConfig); + sourceConfig_ = tmpConfig; + delete config; + systemBus_.connect(CALL_SERVICE_NAME, CALL_SERVICE_PATH, CALL_SERVICE_INTERFACE, @@ -60,22 +82,9 @@ void CallListener::begin() this, SLOT(callTerminate())); - contactManager_ = new ContactManager; + qDebug() << "Starting..."; - eniro_ = new Eniro(Eniro::stringToSite(Settings::instance()->get("site"))); - - eniro_->setMaxResults(1); - eniro_->setFindNumber(false); - - connect(eniro_, SIGNAL(requestFinished(QVector const&, - Eniro::SearchDetails const&, bool)), - this, SLOT(requestFinished(QVector const&, - Eniro::SearchDetails const&, bool))); - - box_ = new InformationBox(); - label_ = new QLabel("", box_); - label_->setMargin(10); - box_->setWidget(label_); + return true; } @@ -95,49 +104,70 @@ void CallListener::end() this, SLOT(callTerminate())); - delete eniro_; - eniro_ = 0; - delete box_; - box_ = 0; - delete label_; - label_ = 0; + searchClose(); + sourceConfig_.clear(); + } -void CallListener::search(Eniro::SearchDetails const& details) +void CallListener::search(Source::SearchDetails const& details) { - label_->setText(tr("Searching...")); - box_->show(); + if(currentCall_) + { + delete currentCall_; + } + + currentCall_ = new CallDetails; + currentCall_->number = details.query; + currentCall_->time = QDateTime::currentDateTime().toTime_t(); + currentCall_->answered = false; - DB::connect(); + searchInit(); - QSqlQuery query; - query.prepare("SELECT name, street, city FROM cache WHERE number = :number"); - query.bindValue(":number", details.query); + Source::Result result; - if(query.exec() && query.next()) + if(Cache::instance().findItem(details.query, result)) { - showResult(createResult(query.value(0).toString(), - query.value(1).toString(), - query.value(2).toString())); + qDebug() << "Found from cache"; + + showDelayedResult(createResult(result.name, + result.street, + result.city), BANNER_DELAY); + + currentCall_->result = result; } else { - eniro_->search(details); - } + retries_ = 0; + + if(!handleConnection()) + { + qDebug() << "Unable to connect"; + return; + } - DB::disconnect(); + showDelayedResult(tr("Searching..."), BANNER_DELAY); + + source_->search(details); + } } -void CallListener::requestFinished(QVector const& results, - Eniro::SearchDetails const& details, +void CallListener::requestFinished(QVector const& results, + Source::SearchDetails const& details, bool error) { - qDebug() << "Found: " << results.size(); + /*if(closeConnection_) + { + closeConnection_ = false; + ConnectionManager cm; + cm.disconnect(true); + }*/ + + qDebug() << "Request finished"; // If box is not visible, the call must have been terminated already - if(!box_->isVisible()) + if(!initialized_ || !box_->isVisible() || !currentCall_) { return; } @@ -146,47 +176,55 @@ void CallListener::requestFinished(QVector const& results, if(error) { - qDebug() << "Error: " << eniro_->errorString(); - message = tr("Search failed:") + " " + eniro_->errorString(); - } - else if(results.size() == 0) - { - message = tr("Phone number was not found"); - } - else - { - message = createResult(results.at(0).name, results.at(0).street, results.at(0).city); - QSqlQuery query; - - DB::connect(); - - query.prepare("INSERT INTO cache(number, name, street, city) VALUES(:number, :name, :street, :city)"); - query.bindValue(":number", details.query); - query.bindValue(":name", results.at(0).name); - query.bindValue(":street", results.at(0).street); - query.bindValue(":city", results.at(0).city); + qDebug() << "Error: " << source_->errorString(); - if(!query.exec()) + if(retries_ < SEARCH_RETRIES && retries_ >= 0) { - qDebug() << "Unable to save cache"; + retries_++; + source_->search(Source::SearchDetails(currentCall_->number, "", Source::BOTH)); + return; } - - QString cacheSize = Settings::instance()->get("cache_size"); - - // Delete old entries from cache - if(cacheSize.toInt() > 0) + else { - if(!query.exec("DELETE c1 FROM cache AS c1 LEFT JOIN (SELECT id FROM cache ORDER BY id DESC LIMIT " + cacheSize + ") AS c2 ON c1.id = c2.id WHERE c2.id IS NULL")) + timedMessage_ = ""; + QString errorString; + Source::Error error = source_->error(); + + switch(error) { - qDebug() << "Unable to delete old cache entries"; + case Source::TIMEOUT: + errorString = tr("Request timed out"); + break; + default: + errorString = source_->errorString(); + break; } - } - DB::disconnect(); + showError(tr("Searching failed:") + " " + errorString + "."); + } } + else + { + timedMessage_ = ""; - showResult(message); + if(results.size() == 0) + { + message = tr("Phone number was not found"); + showResult(message); + } + else + { + message = createResult(results.at(0).name, results.at(0).street, + results.at(0).city); + showResult(message); + Source::Result result = results.at(0); + result.number = details.query; + Cache::instance().addItem(result); + currentCall_->result = results.at(0); + } + } + retries_ = -1; } QString CallListener::createResult(QString const& name, QString const& street, QString const& city) @@ -210,17 +248,34 @@ QString CallListener::createResult(QString const& name, QString const& street, Q void CallListener::showResult(QString const& text) { - label_->setText(text); - box_->hide(); + if(!initialized_) + { + return; + } + + label_->setText("" + text + ""); + + if(box_->isVisible()) + { + box_->hide(); + } + box_->show(); } void CallListener::incomingCall(QDBusObjectPath path, QString number) { - qDebug() << number; + if(number.isEmpty()) + { + qDebug() << "Unknown caller without number"; + return; + } - if(!contactManager_->numberExists(number)) + ContactManager cm; + + if(!cm.numberExists(number)) { + qDebug() << "Number doesn't exist: " << number; systemBus_.connect(CALL_SERVICE_NAME, path.path(), @@ -229,11 +284,363 @@ void CallListener::incomingCall(QDBusObjectPath path, QString number) this, SLOT(callTerminate())); - search(Eniro::SearchDetails(number)); + systemBus_.connect(CALL_SERVICE_NAME, + path.path(), + CALL_SERVICE_INSTANCE_NAME, + CALL_SIGNAL_ANSWERED, + this, + SLOT(handleAnswer())); + + search(Source::SearchDetails(number, "", Source::BOTH)); + } + else + { + qDebug() << "Number exists: " << number; } } void CallListener::callTerminate() { - box_->hide(); + if(box_ && box_->isVisible()) + { + box_->hide(); + } + + if(currentCall_) + { + currentCall_->result.number = currentCall_->number; + Cache::instance().logItem(currentCall_->result, !currentCall_->answered, currentCall_->time); + delete currentCall_; + currentCall_ = 0; + } + + searchClose(); +} + +void CallListener::handleAnswer() +{ + qDebug() << "Answered"; + + if(currentCall_) + { + currentCall_->answered = true; + } +} + +void CallListener::showDelayedResult(QString const& text, int delay) +{ + timedMessage_ = text; + QTimer::singleShot(delay, this, SLOT(showTimedMessage())); +} + +void CallListener::showTimedMessage() +{ + if(timedMessage_.size() == 0 || !initialized_) + { + return; + } + + showResult(timedMessage_); + + timedMessage_ = ""; +} + +void CallListener::searchInit() +{ + qDebug() << "Initializing search..."; + + if(initialized_) + { + qDebug() << "Already initialized"; + return; + } + + source_ = Source::getSource(sourceId_); + SourceCoreConfig* config = SourceCoreConfig::getCoreConfig(sourceId_); + config->loadFromConfig(sourceConfig_); + config->apply(source_); + delete config; + source_->setMaxResults(1); + source_->setFindNumber(false); + source_->setTimeout(REQUEST_TIMEOUT); + + connect(source_, SIGNAL(requestFinished(QVector const&, + Source::SearchDetails const&, bool)), + this, SLOT(requestFinished(QVector const&, + Source::SearchDetails const&, bool))); + box_ = new InformationBox; + label_ = new QLabel("", box_); + label_->setMargin(8); + label_->setWordWrap(true); + box_->setWidget(label_); + initialized_ = true; +} + +void CallListener::searchClose() +{ + if(!initialized_) + { + return; + } + + initialized_ = false; + + qDebug() << "Closing search..."; + + if(source_) + { + disconnect(source_, SIGNAL(requestFinished(QVector const&, + Source::SearchDetails const&, bool)), + this, SLOT(requestFinished(QVector const&, + Source::SearchDetails const&, bool))); + } + + delete source_; + source_ = 0; + delete box_; + box_ = 0; + label_ = 0; + + if(closeConnection_) + { + QTimer::singleShot(500, this, SLOT(closeConnection())); + } +} + +void CallListener::closeConnection() +{ + if(closeConnection_) + { + closeConnection_ = false; + ConnectionManager cm; + cm.disconnect(true); + } +} + +bool CallListener::handleConnection() +{ + if(!initialized_) + { + return false; + } + + ConnectionManager cm; + + if(cm.isConnected()) + { + cm.connect(); + closeConnection_ = false; + return true; + } + + closeConnection_ = true; + + Settings::ConnectionType configType = Settings::instance()->getConnectionType(); + + if(configType == Settings::ALWAYS_ASK) + { + showError(tr("Automatic connecting is not allowed by settings."), BANNER_DELAY); + return false; + } + + showDelayedResult(tr("Connecting..."), BANNER_DELAY); + + ConnectionManager::Connection best; + + ConnectionManager::ConnectionType lookupType = ConnectionManager::NO_TYPE; + + switch(configType) + { + case Settings::WLAN: + lookupType = ConnectionManager::WLAN; + break; + case Settings::GPRS: + lookupType = ConnectionManager::GPRS; + break; + default: + lookupType = ConnectionManager::NO_TYPE; + break; + } + + int cretries = 0; + int scans = 0; + bool found = false; + int maxScans = GPRS_SCANS; + + if(lookupType != ConnectionManager::GPRS) + { + maxScans = WLAN_SCANS; + } + + while(cretries < CONNECTION_LOOKUP_RETRIES) + { + if(!initialized_) + { + return false; + } + + if(scans < maxScans) + { + if(cm.getBestConnection(best, lookupType)) + { + found = true; + } + + scans++; + } + + // If there is only gprs connection available, + // make sure that we are on 3g network + if(found && (best.type != ConnectionManager::GPRS || is3g())) + { + break; + } + + if(found) + { + sleep(WAIT_BETWEEN_RETRIES); + } + + qDebug() << "No connections found, retrying..."; + + cretries++; + + } + + if(cretries >= CONNECTION_LOOKUP_RETRIES) + { + showError(tr("No available 3G or WLAN networks found.")); + return false; + } + + int retries = 0; + + while(retries < CONNECT_RETRIES) + { + if(!initialized_) + { + return false; + } + + qDebug() << "Connecting to " << best.name << " (" << best.id << ")"; + + if(cm.connect(best.id)) + { + break; + } + else if(cm.error() == ConnectionManager::INVALID_IAP) + { + showError(tr("Selected access point doesn't exist.")); + return false; + } + + retries++; + + qDebug() << "Unable to connect, retrying..."; + + if(retries < CONNECT_RETRIES) + { + sendRetrySignal(best.id, false); + sleep(WAIT_BETWEEN_RETRIES); + } + + } + + if(retries >= CONNECT_RETRIES) + { + sendRetrySignal(best.id, false); + + if(initialized_) + { + showError(tr("Unable to connect to network.")); + } + + return false; + } + + return initialized_; +} + +void CallListener::showError(QString const& msg, int timeout) +{ + qDebug() << "Error: " << msg; + + if(!initialized_ || !box_) + { + return; + } + + box_->setTimeout(ERROR_BANNER_TIMEOUT); + + if(timeout) + { + showDelayedResult(msg, timeout); + } + else + { + showResult(msg); + } +} + +bool CallListener::is3g() +{ + QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.phone.net", + "/com/nokia/phone/net", + "Phone.Net", + "get_registration_status"); + + QDBusMessage rep = systemBus_.call(msg); + + if(rep.type() == QDBusMessage::ErrorMessage) + { + qDebug() << "Unable to get network status"; + return false; + } + + uint status = rep.arguments().value(6).toUInt(); + + if(status & 0x10 || status & 0x08) + { + return true; + } + + return false; +} + +void CallListener::sendRetrySignal(QString const& iap, bool retry) +{ + QDBusMessage msg = QDBusMessage::createSignal("/com/nokia/icd_ui", + "com.nokia.icd_ui", + "retry"); + + QList arguments; + arguments.append(QVariant(iap)); + arguments.append(QVariant(retry)); + msg.setArguments(arguments); + + QDBusConnection::systemBus().send(msg); + + qDebug() << "Retry signal sent"; +} + +void CallListener::timerEvent(QTimerEvent* event) +{ + Q_UNUSED(event); + killTimer(timer_); + timer_ = 0; +} + +void CallListener::sleep(int ms) +{ + if(timer_) + { + killTimer(timer_); + } + + timer_ = startTimer(ms); + + while(timer_) + { + QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); + } }