2 * hfdialer - Hands Free Voice Call Manager
3 * Copyright (c) 2012, Intel Corporation.
5 * This program is licensed under the terms and conditions of the
6 * Apache License, version 2.0. The full text of the Apache License is at
7 * http://www.apache.org/licenses/LICENSE-2.0
13 #include "callproxy.h"
14 #include "managerproxy.h"
16 // Returns a valid QDateTime if parsable as such, otherwise the result
18 static QDateTime qDateTimeFromOfono(const QString &val)
26 // NOTE: Ofono formats time to string with the following format spec:
27 // %Y-%m-%dT%H:%M:%S%z (for example: "2001-10-19T10:32:30-05:00")
29 // Start by trying to parse this as an ISODate "YYYY-MM-DDTHH:MM:SSTZD"
30 result = QDateTime::fromString(val,Qt::ISODate);
32 qDebug() << QString("Converted %1 with Qt::ISODate: %2")
34 .arg(result.toString());
37 if (!result.isValid()) {
38 // ISODate conversion has failed, fallback to manual method
39 // NOTE: QDateTime::fromString(val, Qt::ISODate) Fails since the date
40 // format from Ofono is in RFC 822 form, but QDateTime can't parse it
42 QByteArray bytes = val.toAscii();
43 const char *str = bytes.constData();
44 if (strptime(str, "%Y-%m-%dT%H:%M:%S%z", &time_tm) != NULL) {
45 time_t t = mktime(&time_tm);
46 if (t >= (time_t)(0)) {
49 qDebug() << QString("Converted %1 with strptime: %2")
51 .arg(result.toString());
56 if (!result.isValid())
57 qCritical() << QString("Format error, unknown date/time: %1")
64 CallProxy::CallProxy(const QString &callPath)
65 : org::ofono::VoiceCall(OFONO_SERVICE,
67 QDBusConnection::systemBus()),
70 m_startTime(QDateTime()),
77 if (!org::ofono::VoiceCall::isValid())
79 qCritical() << QString("Failed to connect to %1 for call %2:\n\t%3")
80 .arg(staticInterfaceName())
82 .arg(lastError().message());
85 QDBusPendingReply<QVariantMap> reply;
86 QDBusPendingCallWatcher *watcher;
88 reply = GetProperties();
89 watcher = new QDBusPendingCallWatcher(reply);
92 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
93 SLOT(getPropertiesFinished(QDBusPendingCallWatcher*)));
96 // Force this to be sync to ensure we have initial properties
97 watcher->waitForFinished();
98 getPropertiesFinished(watcher);
102 SIGNAL(PropertyChanged(const QString&,const QDBusVariant&)),
103 SLOT(propertyChanged(const QString&,const QDBusVariant&)));
104 connect(this, SIGNAL(DisconnectReason(const QString&)),
105 SLOT(disconnectReason(const QString&)));
107 qCritical() << QString("Invalid CallProxy instance: state == %1")
112 CallProxy::~CallProxy()
115 // FIXME: Do something here!!!
118 bool CallProxy::isValid()
121 return (org::ofono::VoiceCall::isValid() &&
123 (m_state != "disconnected"));
126 QString CallProxy::lineID() const
132 QString CallProxy::name() const
138 QString CallProxy::state() const
144 QDateTime CallProxy::startTime() const
150 int CallProxy::duration() const
153 if (m_startTime.isValid())
154 return m_startTime.secsTo(QDateTime::currentDateTime());
159 QString CallProxy::reason() const
165 bool CallProxy::multiparty() const
171 void CallProxy::answer()
175 // ResourceProxy *resource = ResourceProxy::instance();
177 // connect(resource, SIGNAL(answerResourceAcquired()), SLOT(proceedCallAnswer()));
178 // connect(resource, SIGNAL(answerResourceDenied()), SLOT(deniedCallAnswer()));
180 // resource->acquireAnswerResource();
185 void CallProxy::proceedCallAnswer()
189 // ResourceProxy *resource = ResourceProxy::instance();
190 QDBusPendingReply<QDBusObjectPath> reply;
191 QDBusPendingCallWatcher *watcher;
193 // disconnect(resource, SIGNAL(answerResourceAcquired()));
194 // disconnect(resource, SIGNAL(answerResourceDenied()));
197 watcher = new QDBusPendingCallWatcher(reply);
199 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
200 SLOT(answerFinished(QDBusPendingCallWatcher*)));
203 void CallProxy::deniedCallAnswer()
207 // ResourceProxy *resource = ResourceProxy::instance();
209 // disconnect(resource, SIGNAL(answerResourceAcquired()));
210 // disconnect(resource, SIGNAL(answerResourceDenied()));
212 // Hang up the incoming call, if resources to accept it are inavailabe
215 emit ManagerProxy::instance()->callManager()->deniedCallAnswer();
218 void CallProxy::deflect(const QString toNumber)
222 QDBusPendingReply<QDBusObjectPath> reply;
223 QDBusPendingCallWatcher *watcher;
225 reply = Deflect(toNumber);
226 watcher = new QDBusPendingCallWatcher(reply);
228 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
229 SLOT(deflectFinished(QDBusPendingCallWatcher*)));
232 void CallProxy::hangup()
236 QDBusPendingReply<> reply;
237 QDBusPendingCallWatcher *watcher;
240 watcher = new QDBusPendingCallWatcher(reply);
242 connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
243 SLOT(hangupFinished(QDBusPendingCallWatcher*)));
246 void CallProxy::getPropertiesFinished(QDBusPendingCallWatcher *watcher)
250 QDBusPendingReply<QVariantMap> reply = *watcher;
252 if (reply.isError()) {
253 qCritical() << QString("Failed to connect to %1 for call %2:\n\t%3")
254 .arg(staticInterfaceName())
256 .arg(lastError().message());
260 QVariantMap props = reply.value();
264 m_lineid = qdbus_cast<QString>(props["LineIdentification"]);
265 m_name = qdbus_cast<QString>(props["Name"]);
266 m_state = qdbus_cast<QString>(props["State"]);
267 l_start = qdbus_cast<QString>(props["StartTime"]);
268 m_multiparty = qdbus_cast<bool>(props["Multiparty"]);
270 setStartTimeFromString(l_start);
272 // Indicate for this instance, that we've actually performed at least
273 // one round trip call to this VoiceCall and we are in sync with it
277 void CallProxy::answerFinished(QDBusPendingCallWatcher *watcher)
280 QDBusPendingReply<QDBusObjectPath> reply = *watcher;
282 qCritical() << QString("Answer() Failed: %1 - %2")
283 .arg(reply.error().name())
284 .arg(reply.error().message());
287 void CallProxy::deflectFinished(QDBusPendingCallWatcher *watcher)
290 QDBusPendingReply<QDBusObjectPath> reply = *watcher;
292 qCritical() << QString("Deflect() Failed: %1 - %2")
293 .arg(reply.error().name())
294 .arg(reply.error().message());
297 void CallProxy::hangupFinished(QDBusPendingCallWatcher *watcher)
300 QDBusPendingReply<> reply = *watcher;
302 qCritical() << QString("Hangup() Failed: %1 - %2")
303 .arg(reply.error().name())
304 .arg(reply.error().message());
307 void CallProxy::propertyChanged(const QString &in0, const QDBusVariant &in1)
311 if (in0 == "LineIdentification") {
312 m_lineid = qdbus_cast<QString>(in1.variant());
314 } else if (in0 == "State") {
315 m_state = qdbus_cast<QString>(in1.variant());
317 } else if (in0 == "StartTime") {
318 setStartTimeFromString(qdbus_cast<QString>(in1.variant()));
319 } else if (in0 == "Multiparty") {
320 m_multiparty = qdbus_cast<bool>(in1.variant());
321 emit multipartyChanged();
323 qDebug() << QString("Unexpected property \"%1\" changed...").arg(in0);
327 void CallProxy::disconnectReason(const QString &in0)
331 emit callDisconnected(in0);
334 void CallProxy::setStartTimeFromString(const QString &val)
340 m_startTime = qDateTimeFromOfono(val);
342 if (!m_startTime.isValid())
343 m_startTime = QDateTime::QDateTime::currentDateTime();