2
* Copyright (C) 2013 Canonical, Ltd.
4
* This program is free software: you can redistribute it and/or modify it under
5
* the terms of the GNU General Public License version 3, as published by
6
* the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful, but WITHOUT
9
* ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
* SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authors: Tiago Salem Herrmann <tiago.herrmann@canonical.com>
22
#include <TelepathyQt/PendingReady>
23
#include <TelepathyQt/ChannelClassSpec>
24
#include <TelepathyQt/ClientRegistrar>
25
#include <TelepathyQt/CallChannel>
26
#include <TelepathyQt/TextChannel>
28
Approver::Approver(QObject* parent)
29
: QObject(parent), Tp::AbstractClientApprover(channelFilters())
37
Tp::ChannelClassSpecList Approver::channelFilters() const
39
Tp::ChannelClassSpecList specList;
40
specList << Tp::ChannelClassSpec::textChat()
41
<< Tp::ChannelClassSpec::audioCall();
46
void Approver::addDispatchOperation(const Tp::MethodInvocationContextPtr<> &context,
47
const Tp::ChannelDispatchOperationPtr &dispatchOperation)
49
bool willHandle = false;
51
QList<Tp::ChannelPtr> channels = dispatchOperation->channels();
52
Q_FOREACH (Tp::ChannelPtr channel, channels) {
54
Tp::TextChannelPtr textChannel = Tp::TextChannelPtr::dynamicCast(channel);
55
if (!textChannel.isNull()) {
56
// right now we are not using any of the text channel's features in the approver
57
// so no need to call becomeReady() on it.
63
Tp::CallChannelPtr callChannel = Tp::CallChannelPtr::dynamicCast(channel);
64
if (!callChannel.isNull()) {
65
Tp::PendingReady *pr = callChannel->becomeReady(Tp::Features()
66
<< Tp::CallChannel::FeatureCore
67
<< Tp::CallChannel::FeatureCallState
68
<< Tp::CallChannel::FeatureLocalHoldState);
69
mChannels[pr] = callChannel;
71
connect(pr, SIGNAL(finished(Tp::PendingOperation*)),
72
SLOT(onChannelReady(Tp::PendingOperation*)));
73
callChannel->setProperty("accountId", QVariant(dispatchOperation->account()->uniqueIdentifier()));
80
mDispatchOps.append(dispatchOperation);
83
context->setFinished();
85
// check if we need to approve channels already or if we should wait.
89
void Approver::processChannels()
91
Q_FOREACH (Tp::ChannelDispatchOperationPtr dispatchOperation, mDispatchOps) {
92
QList<Tp::ChannelPtr> channels = dispatchOperation->channels();
93
Q_FOREACH (Tp::ChannelPtr channel, channels) {
94
// approve only text channels
95
Tp::TextChannelPtr textChannel = Tp::TextChannelPtr::dynamicCast(channel);
96
if (textChannel.isNull()) {
100
if (dispatchOperation->possibleHandlers().contains(TELEPHONY_SERVICE_HANDLER)) {
101
dispatchOperation->handleWith(TELEPHONY_SERVICE_HANDLER);
102
mDispatchOps.removeAll(dispatchOperation);
104
// FIXME: this shouldn't happen, but in any case, we need to check what to do when
105
// the phone app client is not available
110
void Approver::acceptCall()
112
Q_FOREACH (Tp::ChannelDispatchOperationPtr dispatchOperation, mDispatchOps) {
113
QList<Tp::ChannelPtr> channels = dispatchOperation->channels();
114
Q_FOREACH (Tp::ChannelPtr channel, channels) {
115
if (dispatchOperation->possibleHandlers().contains(TELEPHONY_SERVICE_HANDLER)) {
116
dispatchOperation->handleWith(TELEPHONY_SERVICE_HANDLER);
117
mDispatchOps.removeAll(dispatchOperation);
123
void Approver::rejectCall()
125
Q_FOREACH (Tp::ChannelDispatchOperationPtr dispatchOperation, mDispatchOps) {
126
QList<Tp::ChannelPtr> channels = dispatchOperation->channels();
127
Q_FOREACH (Tp::ChannelPtr channel, channels) {
128
if (dispatchOperation->possibleHandlers().contains(TELEPHONY_SERVICE_HANDLER)) {
129
Tp::PendingOperation *claimop = dispatchOperation->claim();
130
mChannels[claimop] = dispatchOperation->channels().first();
131
connect(claimop, SIGNAL(finished(Tp::PendingOperation*)),
132
this, SLOT(onClaimFinished(Tp::PendingOperation*)));
138
void Approver::onClaimFinished(Tp::PendingOperation* op)
140
if(!op || op->isError()) {
144
Tp::CallChannelPtr callChannel = Tp::CallChannelPtr::dynamicCast(mChannels[op]);
146
Tp::PendingOperation *hangupop = callChannel->hangup(Tp::CallStateChangeReasonUserRequested, TP_QT_ERROR_REJECTED, QString());
147
mChannels[hangupop] = callChannel;
148
connect(hangupop, SIGNAL(finished(Tp::PendingOperation*)),
149
this, SLOT(onHangupFinished(Tp::PendingOperation*)));
153
void Approver::onHangupFinished(Tp::PendingOperation* op)
155
if(!op || op->isError()) {
158
mDispatchOps.removeAll(dispatchOperation(op));
159
mChannels.remove(op);
162
Tp::ChannelDispatchOperationPtr Approver::dispatchOperation(Tp::PendingOperation *op)
164
Tp::ChannelPtr channel = mChannels[op];
165
QString accountId = channel->property("accountId").toString();
166
Q_FOREACH (Tp::ChannelDispatchOperationPtr dispatchOperation, mDispatchOps) {
167
if (dispatchOperation->account()->uniqueIdentifier() == accountId) {
168
return dispatchOperation;
171
return Tp::ChannelDispatchOperationPtr();
174
void Approver::onChannelReady(Tp::PendingOperation *op)