-
Notifications
You must be signed in to change notification settings - Fork 6
/
callchannelobserver.cpp
165 lines (137 loc) · 5.88 KB
/
callchannelobserver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "callchannelobserver.h"
#include <TelepathyQt/Contact>
#include <TelepathyQt/PendingContactInfo>
#include <QContactFetchRequest>
#include <QContactPhoneNumber>
#include <QContactFilter>
#include <QContactDetail>
#include <QContactDisplayLabel>
QTCONTACTS_USE_NAMESPACE
TelepathyMonitor::TelepathyMonitor(QObject *parent):
QObject(parent)
{
Tp::registerTypes();
QTimer::singleShot(0, this, &TelepathyMonitor::accountManagerSetup);
m_contactManager = new QContactManager("galera");
m_contactManager->setParent(this);
}
void TelepathyMonitor::hangupCall(uint cookie)
{
if (m_currentCalls.contains(cookie)) {
m_currentCalls.value(cookie)->hangup();
}
}
void TelepathyMonitor::accept(uint cookie) {
if (m_currentCalls.contains(cookie)) {
m_currentCalls.value(cookie)->accept();
}
}
void TelepathyMonitor::accountManagerSetup()
{
m_accountManager = Tp::AccountManager::create(Tp::AccountFactory::create(QDBusConnection::sessionBus(),
Tp::Account::FeatureCore),
Tp::ConnectionFactory::create(QDBusConnection::sessionBus(),
Tp::Connection::FeatureCore));
connect(m_accountManager->becomeReady(),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(accountManagerReady(Tp::PendingOperation*)));
}
void TelepathyMonitor::accountManagerReady(Tp::PendingOperation* operation)
{
if (operation->isError()) {
qDebug() << "TelepathyMonitor: accountManager init error.";
QTimer::singleShot(1000, this, &TelepathyMonitor::accountManagerSetup); // again
return;
}
qDebug() << "Telepathy account manager ready";
foreach (const Tp::AccountPtr& account, m_accountManager->allAccounts()) {
connect(account->becomeReady(Tp::Account::FeatureCapabilities),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(accountReady(Tp::PendingOperation*)));
}
connect(m_accountManager.data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(newAccount(Tp::AccountPtr)));
}
void TelepathyMonitor::newAccount(const Tp::AccountPtr& account)
{
connect(account->becomeReady(Tp::Account::FeatureCapabilities),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(accountReady(Tp::PendingOperation*)));
}
void TelepathyMonitor::accountReady(Tp::PendingOperation* operation)
{
if (operation->isError()) {
qDebug() << "TelepathyAccount: Operation failed (accountReady)";
return;
}
Tp::PendingReady* pendingReady = qobject_cast<Tp::PendingReady*>(operation);
if (pendingReady == 0) {
qDebug() << "Rejecting account because could not understand ready status";
return;
}
checkAndAddAccount(Tp::AccountPtr::qObjectCast(pendingReady->proxy()));
}
void TelepathyMonitor::onCallStarted(Tp::CallChannelPtr callChannel)
{
m_cookie++;
m_currentCalls.insert(m_cookie, callChannel.data());
m_currentCallStates.insert(m_cookie, Tp::CallStateInitialising);
callChannel->becomeReady(Tp::CallChannel::FeatureCallState);
connect(callChannel.data(), &Tp::CallChannel::callStateChanged, this, &TelepathyMonitor::callStateChanged);
QString number = callChannel->initiatorContact()->id();
// try to match the contact info
QContactFetchRequest *request = new QContactFetchRequest(this);
request->setFilter(QContactPhoneNumber::match(number));
// lambda function to update the notification
QObject::connect(request, &QContactAbstractRequest::stateChanged, [this, request, number](QContactAbstractRequest::State state) {
qDebug() << "request returned";
if (!request || state != QContactAbstractRequest::FinishedState) {
qDebug() << "error fetching contact" << state;
return;
}
QContact contact;
// create the snap decision only after the contact match finishes
if (request->contacts().size() > 0) {
// use the first match
contact = request->contacts().at(0);
qDebug() << "have contact" << contact.detail<QContactDisplayLabel>().label();
emit this->incomingCall(m_cookie, number, contact.detail<QContactDisplayLabel>().label());
} else {
qDebug() << "unknown contact" << number;
emit this->incomingCall(m_cookie, number, QString());
}
});
request->setManager(m_contactManager);
request->start();
}
void TelepathyMonitor::callStateChanged(Tp::CallState state)
{
qDebug() << "call state changed1";
Tp::CallChannel *channel = qobject_cast<Tp::CallChannel*>(sender());
uint cookie = m_currentCalls.key(channel);
qDebug() << "call state changed2" << state << "cookie:" << cookie;
switch (state) {
case Tp::CallStateActive:
emit callStarted(cookie);
m_currentCallStates[cookie] = Tp::CallStateActive;
break;
case Tp::CallStateEnded: {
Tp::CallState oldState = m_currentCallStates.value(cookie);
emit callEnded(cookie, oldState != Tp::CallStateActive);
m_currentCalls.take(cookie);
m_currentCallStates.take(cookie);
break;
}
default:
break;
}
}
void TelepathyMonitor::checkAndAddAccount(const Tp::AccountPtr& account)
{
Tp::ConnectionCapabilities caps = account->capabilities();
// TODO: Later on we will need to filter for the right capabilities, and also allow dynamic account detection
// Don't check caps for now as a workaround for https://bugs.launchpad.net/ubuntu/+source/media-hub/+bug/1409125
// at least until we are able to find out the root cause of it (check rev 107 for the caps check)
auto tcm = new TelepathyCallMonitor(account);
connect(tcm, &TelepathyCallMonitor::callStarted, this, &TelepathyMonitor::onCallStarted);
m_callMonitors.append(tcm);
}