~fboucault/telepathy-ofono/crossbuild_fixes

6 by Tiago Salem Herrmann
add copyright headers
1
/**
19 by Tiago Salem Herrmann
fix copyright year
2
 * Copyright (C) 2013 Canonical, Ltd.
6 by Tiago Salem Herrmann
add copyright headers
3
 *
24.1.2 by Ricardo Salveti de Araujo
* Packaging cleanup
4
 * This program is free software: you can redistribute it and/or modify it under
5
 * the terms of the GNU Lesser General Public License version 3, as published by
6
 * the Free Software Foundation.
7
 *
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
 * Lesser General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public License
6 by Tiago Salem Herrmann
add copyright headers
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24.1.2 by Ricardo Salveti de Araujo
* Packaging cleanup
15
 *
16
 * Authors: Tiago Salem Herrmann <tiago.herrmann@canonical.com>
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
17
 *          Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
6 by Tiago Salem Herrmann
add copyright headers
18
 */
19
1 by Tiago Salem Herrmann
initial commit
20
#include <QDebug>
154.1.1 by Tiago Salem Herrmann
Ensure uniqueName() is really unique. Using the object pointer is error-prone
21
#include <QCryptographicHash>
1 by Tiago Salem Herrmann
initial commit
22
23
#include <TelepathyQt/Constants>
24
#include <TelepathyQt/BaseChannel>
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
25
#include <TelepathyQt/DBusObject>
1 by Tiago Salem Herrmann
initial commit
26
27
// telepathy-ofono
28
#include "connection.h"
51.1.3 by Tiago Salem Herrmann
add PhoneUtils class
29
#include "phoneutils_p.h"
1 by Tiago Salem Herrmann
initial commit
30
#include "protocol.h"
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
31
#include "ofonoconferencecallchannel.h"
1 by Tiago Salem Herrmann
initial commit
32
34.2.1 by Tiago Salem Herrmann
add initial mms support
33
#include "mmsdmessage.h"
34
#include "mmsdservice.h"
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
35
38.1.1 by David Henningsson
Add PulseAudio backend
36
#ifdef USE_PULSEAUDIO
37
#include "qpulseaudioengine.h"
38
#endif
39
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
40
#include "sqlitedatabase.h"
55.2.3 by Tiago Salem Herrmann
move database methods to a separate class: PendingMessagesManager
41
#include "pendingmessagesmanager.h"
91.3.2 by Tiago Salem Herrmann
move SpeakerInterface to AudioOutputsInterface
42
#include "dbustypes.h"
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
43
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
44
static void enable_earpiece()
45
{
38.1.1 by David Henningsson
Add PulseAudio backend
46
#ifdef USE_PULSEAUDIO
149.1.1 by Tiago Salem Herrmann
Move pulseaudio operations to a separate thread.
47
    QPulseAudioEngine::instance()->setCallMode(CallActive, AudioModeBtOrWiredOrEarpiece);
38.1.1 by David Henningsson
Add PulseAudio backend
48
#endif
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
49
}
50
51
static void enable_normal()
52
{
38.1.1 by David Henningsson
Add PulseAudio backend
53
#ifdef USE_PULSEAUDIO
118.1.1 by Tiago Salem Herrmann
give some time before calling enable_normal() so the beeps emited after a terminated call are played
54
    QTimer* timer = new QTimer();
55
    timer->setSingleShot(true);
56
    QObject::connect(timer, &QTimer::timeout, [=](){
149.2.1 by Tiago Salem Herrmann
Unmute before setting the state as CallEnded
57
        QPulseAudioEngine::instance()->setMicMute(false);
149.1.1 by Tiago Salem Herrmann
Move pulseaudio operations to a separate thread.
58
        QPulseAudioEngine::instance()->setCallMode(CallEnded, AudioModeWiredOrSpeaker);
118.1.1 by Tiago Salem Herrmann
give some time before calling enable_normal() so the beeps emited after a terminated call are played
59
        timer->deleteLater();
60
    });
61
    timer->start(2000);
38.1.1 by David Henningsson
Add PulseAudio backend
62
#endif
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
63
}
64
65
static void enable_speaker()
66
{
38.1.1 by David Henningsson
Add PulseAudio backend
67
#ifdef USE_PULSEAUDIO
149.1.1 by Tiago Salem Herrmann
Move pulseaudio operations to a separate thread.
68
    QPulseAudioEngine::instance()->setCallMode(CallActive, AudioModeSpeaker);
38.1.1 by David Henningsson
Add PulseAudio backend
69
#endif
70
}
71
72
static void enable_ringtone()
73
{
74
#ifdef USE_PULSEAUDIO
149.1.1 by Tiago Salem Herrmann
Move pulseaudio operations to a separate thread.
75
    QPulseAudioEngine::instance()->setCallMode(CallRinging, AudioModeWiredOrSpeaker);
38.1.1 by David Henningsson
Add PulseAudio backend
76
#endif
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
77
}
34.2.1 by Tiago Salem Herrmann
add initial mms support
78
1 by Tiago Salem Herrmann
initial commit
79
oFonoConnection::oFonoConnection(const QDBusConnection &dbusConnection,
80
                            const QString &cmName,
81
                            const QString &protocolName,
82
                            const QVariantMap &parameters) :
83
    Tp::BaseConnection(dbusConnection, cmName, protocolName, parameters),
84
    mOfonoModemManager(new OfonoModemManager(this)),
7 by Tiago Salem Herrmann
add online presence support
85
    mHandleCount(0),
34.2.3 by Tiago Salem Herrmann
merge trunk
86
    mMmsdManager(new MMSDManager(this)),
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
87
    mConferenceCall(NULL)
1 by Tiago Salem Herrmann
initial commit
88
{
91.3.7 by Tiago Salem Herrmann
prepare qpulseaudioengine signals to report audio output changes
89
    qRegisterMetaType<AudioOutputList>();
90
    qRegisterMetaType<AudioOutput>();
67.1.1 by Tiago Salem Herrmann
use modem object path provided instead of automatic selection
91
    OfonoModem::SelectionSetting setting = OfonoModem::AutomaticSelect;
95.1.1 by Tiago Salem Herrmann
Check if the mms service matches the modem object path
92
    mModemPath = parameters["modem-objpath"].toString();
93
    if (!mModemPath.isEmpty()) {
67.1.1 by Tiago Salem Herrmann
use modem object path provided instead of automatic selection
94
        setting = OfonoModem::ManualSelect;
95
    }
95.1.1 by Tiago Salem Herrmann
Check if the mms service matches the modem object path
96
    mOfonoMessageManager = new OfonoMessageManager(setting, mModemPath);
97
    mOfonoVoiceCallManager = new OfonoVoiceCallManager(setting, mModemPath);
98
    mOfonoCallVolume = new OfonoCallVolume(setting, mModemPath);
99
    mOfonoNetworkRegistration = new OfonoNetworkRegistration(setting, mModemPath);
100
    mOfonoMessageWaiting = new OfonoMessageWaiting(setting, mModemPath);
101
    mOfonoSupplementaryServices = new OfonoSupplementaryServices(setting, mModemPath);
95.2.3 by Tiago Salem Herrmann
merge trunk
102
    mOfonoSimManager = new OfonoSimManager(setting, mModemPath);
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
103
    mOfonoModem = mOfonoSimManager->modem();
67.1.1 by Tiago Salem Herrmann
use modem object path provided instead of automatic selection
104
120.2.7 by Tiago Salem Herrmann
change selfHandle when the actual phone number is retrieved
105
    if (mOfonoSimManager->subscriberNumbers().size() > 0) {
106
        setSelfHandle(newHandle(mOfonoSimManager->subscriberNumbers()[0]));
107
    } else {
108
        setSelfHandle(newHandle(""));
109
    }
1 by Tiago Salem Herrmann
initial commit
110
111
    setConnectCallback(Tp::memFun(this,&oFonoConnection::connect));
112
    setInspectHandlesCallback(Tp::memFun(this,&oFonoConnection::inspectHandles));
113
    setRequestHandlesCallback(Tp::memFun(this,&oFonoConnection::requestHandles));
114
    setCreateChannelCallback(Tp::memFun(this,&oFonoConnection::createChannel));
115
5 by Tiago Salem Herrmann
- rename some methods
116
    // initialise requests interface (Connection.Interface.Requests)
1 by Tiago Salem Herrmann
initial commit
117
    requestsIface = Tp::BaseConnectionRequestsInterface::create(this);
5 by Tiago Salem Herrmann
- rename some methods
118
119
    // set requestable text channel properties
1 by Tiago Salem Herrmann
initial commit
120
    Tp::RequestableChannelClass text;
121
    text.fixedProperties[TP_QT_IFACE_CHANNEL+".ChannelType"] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
122
    text.fixedProperties[TP_QT_IFACE_CHANNEL+".TargetHandleType"]  = Tp::HandleTypeContact;
123
    text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetHandle");
124
    text.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetID");
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
125
    text.allowedProperties.append(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"));
1 by Tiago Salem Herrmann
initial commit
126
5 by Tiago Salem Herrmann
- rename some methods
127
    // set requestable call channel properties
1 by Tiago Salem Herrmann
initial commit
128
    Tp::RequestableChannelClass call;
129
    call.fixedProperties[TP_QT_IFACE_CHANNEL+".ChannelType"] = TP_QT_IFACE_CHANNEL_TYPE_CALL;
130
    call.fixedProperties[TP_QT_IFACE_CHANNEL+".TargetHandleType"]  = Tp::HandleTypeContact;
2 by Tiago Salem Herrmann
- add call channel support
131
    call.fixedProperties[TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialAudio"]  = true;
1 by Tiago Salem Herrmann
initial commit
132
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetHandle");
133
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL+".TargetID");
2 by Tiago Salem Herrmann
- add call channel support
134
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialAudio");
135
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialVideo");
136
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialAudioName");
137
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialVideoName");
138
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".InitialTransport");
139
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_TYPE_CALL+".HardwareStreaming");
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
140
    call.allowedProperties.append(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialChannels"));
1 by Tiago Salem Herrmann
initial commit
141
142
    requestsIface->requestableChannelClasses << text << call;
143
144
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(requestsIface));
145
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
146
    // init presence interface
7 by Tiago Salem Herrmann
add online presence support
147
    simplePresenceIface = Tp::BaseConnectionSimplePresenceInterface::create();
148
    simplePresenceIface->setSetPresenceCallback(Tp::memFun(this,&oFonoConnection::setPresence));
149
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(simplePresenceIface));
150
82.1.1 by Gustavo Pichorim Boiko
Expose the emergency numbers via DBus to clients.
151
    // init custom emergency mode interface (not provided by telepathy
152
    emergencyModeIface = BaseConnectionEmergencyModeInterface::create();
153
    emergencyModeIface->setEmergencyNumbersCallback(Tp::memFun(this,&oFonoConnection::emergencyNumbers));
154
    QObject::connect(mOfonoVoiceCallManager, SIGNAL(emergencyNumbersChanged(QStringList)),
155
                     emergencyModeIface.data(), SLOT(setEmergencyNumbers(QStringList)));
156
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(emergencyModeIface));
107.4.2 by Tiago Salem Herrmann
update emergency numbers during startup
157
    emergencyModeIface->setEmergencyNumbers(mOfonoVoiceCallManager->emergencyNumbers());
124.1.1 by Tiago Salem Herrmann
add a fakeEmergencyNumber property for testing
158
    emergencyModeIface->setFakeEmergencyNumber(parameters["fakeEmergencyNumber"].toString());
82.1.1 by Gustavo Pichorim Boiko
Expose the emergency numbers via DBus to clients.
159
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
160
    // init custom voicemail interface (not provided by telepathy)
161
    voicemailIface = BaseConnectionVoicemailInterface::create();
162
    voicemailIface->setVoicemailCountCallback(Tp::memFun(this,&oFonoConnection::voicemailCount));
163
    voicemailIface->setVoicemailIndicatorCallback(Tp::memFun(this,&oFonoConnection::voicemailIndicator));
164
    voicemailIface->setVoicemailNumberCallback(Tp::memFun(this,&oFonoConnection::voicemailNumber));
165
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(voicemailIface));
166
67.2.1 by Tiago Salem Herrmann
add initial ussd support
167
    supplementaryServicesIface = BaseConnectionUSSDInterface::create();
168
    supplementaryServicesIface->setInitiateCallback(Tp::memFun(this,&oFonoConnection::USSDInitiate));
169
    supplementaryServicesIface->setRespondCallback(Tp::memFun(this,&oFonoConnection::USSDRespond));
170
    supplementaryServicesIface->setCancelCallback(Tp::memFun(this,&oFonoConnection::USSDCancel));
67.2.2 by Tiago Salem Herrmann
fix dbus introspection
171
    supplementaryServicesIface->StateChanged(mOfonoSupplementaryServices->state());
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
172
    supplementaryServicesIface->setSerial(mOfonoModem->serial());
67.2.2 by Tiago Salem Herrmann
fix dbus introspection
173
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(supplementaryServicesIface));
67.2.1 by Tiago Salem Herrmann
add initial ussd support
174
7 by Tiago Salem Herrmann
add online presence support
175
    // Set Presence
176
    Tp::SimpleStatusSpec presenceOnline;
177
    presenceOnline.type = Tp::ConnectionPresenceTypeAvailable;
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
178
    presenceOnline.maySetOnSelf = false;
179
    presenceOnline.canHaveMessage = true;
7 by Tiago Salem Herrmann
add online presence support
180
181
    Tp::SimpleStatusSpec presenceOffline;
182
    presenceOffline.type = Tp::ConnectionPresenceTypeOffline;
183
    presenceOffline.maySetOnSelf = false;
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
184
    presenceOffline.canHaveMessage = true;
185
186
    Tp::SimpleStatusSpec presenceAway;
187
    presenceAway.type = Tp::ConnectionPresenceTypeAway;
188
    presenceAway.maySetOnSelf = false;
189
    presenceAway.canHaveMessage = true;
7 by Tiago Salem Herrmann
add online presence support
190
191
    Tp::SimpleStatusSpecMap statuses;
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
192
    statuses.insert(QLatin1String("registered"), presenceOnline);
193
    statuses.insert(QLatin1String("roaming"), presenceOnline);
194
    statuses.insert(QLatin1String("flightmode"), presenceOffline);
195
    statuses.insert(QLatin1String("nosim"), presenceOffline);
196
    statuses.insert(QLatin1String("nomodem"), presenceOffline);
107.3.3 by Tiago Salem Herrmann
declare simlocked state
197
    statuses.insert(QLatin1String("simlocked"), presenceAway);
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
198
    statuses.insert(QLatin1String("unregistered"), presenceAway);
199
    statuses.insert(QLatin1String("denied"), presenceAway);
200
    statuses.insert(QLatin1String("unknown"), presenceAway);
201
    statuses.insert(QLatin1String("searching"), presenceAway);
7 by Tiago Salem Herrmann
add online presence support
202
203
    simplePresenceIface->setStatuses(statuses);
204
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
205
    if (mOfonoModem->isValid()) {
206
        supplementaryServicesIface->setSerial(mOfonoModem->serial());
7 by Tiago Salem Herrmann
add online presence support
207
    }
208
    // force update current presence
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
209
    updateOnlineStatus();
7 by Tiago Salem Herrmann
add online presence support
210
211
    contactsIface = Tp::BaseConnectionContactsInterface::create();
212
    contactsIface->setGetContactAttributesCallback(Tp::memFun(this,&oFonoConnection::getContactAttributes));
213
    contactsIface->setContactAttributeInterfaces(QStringList()
214
                                                 << TP_QT_IFACE_CONNECTION
215
                                                 << TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE);
216
    plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(contactsIface));
217
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
218
    QObject::connect(mOfonoModem, SIGNAL(onlineChanged(bool)), SLOT(updateOnlineStatus()));
103.1.1 by Tiago Salem Herrmann
set model serial when it changes
219
    QObject::connect(mOfonoModem, SIGNAL(serialChanged(QString)), supplementaryServicesIface.data(), SLOT(setSerial(QString)));
95.2.5 by Tiago Salem Herrmann
- refresh properties when interfaces become available
220
    QObject::connect(mOfonoModem, SIGNAL(interfacesChanged(QStringList)), SLOT(updateOnlineStatus()));
5 by Tiago Salem Herrmann
- rename some methods
221
    QObject::connect(mOfonoMessageManager, SIGNAL(incomingMessage(QString,QVariantMap)), this, SLOT(onOfonoIncomingMessage(QString,QVariantMap)));
60.4.2 by Tiago Salem Herrmann
add class 0 sms support
222
    QObject::connect(mOfonoMessageManager, SIGNAL(immediateMessage(QString,QVariantMap)), this, SLOT(onOfonoImmediateMessage(QString,QVariantMap)));
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
223
    QObject::connect(mOfonoMessageManager, SIGNAL(statusReport(QString,QVariantMap)), this, SLOT(onDeliveryReportReceived(QString,QVariantMap)));
5 by Tiago Salem Herrmann
- rename some methods
224
    QObject::connect(mOfonoVoiceCallManager, SIGNAL(callAdded(QString,QVariantMap)), SLOT(onOfonoCallAdded(QString, QVariantMap)));
107.4.3 by Tiago Salem Herrmann
refresh emergency numbers when VoiceCallManager interface validity changes
225
    QObject::connect(mOfonoVoiceCallManager, SIGNAL(validityChanged(bool)), SLOT(onValidityChanged(bool)));
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
226
    QObject::connect(mOfonoSimManager, SIGNAL(validityChanged(bool)), SLOT(onValidityChanged(bool)));
227
    QObject::connect(mOfonoSimManager, SIGNAL(presenceChanged(bool)), SLOT(updateOnlineStatus()));
107.3.1 by Tiago Salem Herrmann
report away status when sim is locked
228
    QObject::connect(mOfonoSimManager, SIGNAL(pinRequiredChanged(QString)), SLOT(updateOnlineStatus()));
120.2.7 by Tiago Salem Herrmann
change selfHandle when the actual phone number is retrieved
229
    QObject::connect(mOfonoSimManager, SIGNAL(subscriberNumbersChanged(QStringList)), SLOT(updateOnlineStatus()));
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
230
    QObject::connect(mOfonoNetworkRegistration, SIGNAL(statusChanged(QString)), SLOT(updateOnlineStatus()));
95.2.2 by Tiago Salem Herrmann
update status when network name changes
231
    QObject::connect(mOfonoNetworkRegistration, SIGNAL(nameChanged(QString)), SLOT(updateOnlineStatus()));
149.4.10 by Tiago Salem Herrmann
Also use SimManager interface to retrieve mobile country code
232
    QObject::connect(mOfonoNetworkRegistration, SIGNAL(mccChanged(QString)), SLOT(updateOnlineStatus(QString)));
116.1.2 by Tiago Salem Herrmann
update network properties when the interface validity changes
233
    QObject::connect(mOfonoNetworkRegistration, SIGNAL(validityChanged(bool)), SLOT(onValidityChanged(bool)));
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
234
    QObject::connect(mOfonoMessageWaiting, SIGNAL(voicemailMessageCountChanged(int)), voicemailIface.data(), SLOT(setVoicemailCount(int)));
235
    QObject::connect(mOfonoMessageWaiting, SIGNAL(voicemailWaitingChanged(bool)), voicemailIface.data(), SLOT(setVoicemailIndicator(bool)));
88.1.1 by Tiago Salem Herrmann
add VoicemailNumberChanged() signal
236
    QObject::connect(mOfonoMessageWaiting, SIGNAL(voicemailMailboxNumberChanged(QString)), voicemailIface.data(), SLOT(setVoicemailNumber(QString)));
34.2.1 by Tiago Salem Herrmann
add initial mms support
237
238
    QObject::connect(mMmsdManager, SIGNAL(serviceAdded(const QString&)), SLOT(onMMSDServiceAdded(const QString&)));
239
    QObject::connect(mMmsdManager, SIGNAL(serviceRemoved(const QString&)), SLOT(onMMSDServiceRemoved(const QString&)));
240
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
241
    // update audio route
242
    QObject::connect(mOfonoVoiceCallManager, SIGNAL(callAdded(QString,QVariantMap)), SLOT(updateAudioRoute()));
243
    QObject::connect(mOfonoVoiceCallManager, SIGNAL(callRemoved(QString)), SLOT(updateAudioRoute()));
34.2.3 by Tiago Salem Herrmann
merge trunk
244
101.1.1 by Ricardo Salveti de Araujo
Improve event handling from pulse, also exporting mode changes.
245
#ifdef USE_PULSEAUDIO
246
    // update audio modes
247
    QObject::connect(QPulseAudioEngine::instance(), SIGNAL(audioModeChanged(AudioMode)), SLOT(onAudioModeChanged(AudioMode)));
248
    QObject::connect(QPulseAudioEngine::instance(), SIGNAL(availableAudioModesChanged(AudioModes)), SLOT(onAvailableAudioModesChanged(AudioModes)));
107.2.2 by Ricardo Salveti de Araujo
Better handling PA_DISABLED
249
250
    // check if we should indeed use pulseaudio
251
    QByteArray pulseAudioDisabled = qgetenv("PA_DISABLED");
252
    mHasPulseAudio = true;
253
    if (!pulseAudioDisabled.isEmpty())
254
        mHasPulseAudio = false;
101.1.1 by Ricardo Salveti de Araujo
Improve event handling from pulse, also exporting mode changes.
255
#endif
256
67.2.1 by Tiago Salem Herrmann
add initial ussd support
257
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(notificationReceived(const QString &)), supplementaryServicesIface.data(), SLOT(NotificationReceived(const QString &)));
258
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(requestReceived(const QString &)), supplementaryServicesIface.data(), SLOT(RequestReceived(const QString &)));
259
260
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(initiateUSSDComplete(const QString &)), supplementaryServicesIface.data(), SLOT(InitiateUSSDComplete(const QString &)));
261
262
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(barringComplete(const QString &, const QString &, const QVariantMap &)), 
263
        supplementaryServicesIface.data(), SLOT(BarringComplete(const QString &, const QString &, const QVariantMap &)));
264
265
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(forwardingComplete(const QString &, const QString &, const QVariantMap &)), 
266
        supplementaryServicesIface.data(), SLOT(ForwardingComplete(const QString &, const QString &, const QVariantMap &)));
267
268
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(waitingComplete(const QString &, const QVariantMap &)), 
269
        supplementaryServicesIface.data(), SLOT(WaitingComplete(const QString &, const QVariantMap &)));
270
271
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(callingLinePresentationComplete(const QString &, const QString &)), 
272
        supplementaryServicesIface.data(), SLOT(CallingLinePresentationComplete(const QString &, const QString &)));
273
274
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(connectedLinePresentationComplete(const QString &, const QString &)), 
275
        supplementaryServicesIface.data(), SLOT(ConnectedLinePresentationComplete(const QString &, const QString &)));
276
277
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(callingLineRestrictionComplete(const QString &, const QString &)), 
278
        supplementaryServicesIface.data(), SLOT(CallingLineRestrictionComplete(const QString &, const QString &)));
279
280
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(connectedLineRestrictionComplete(const QString &, const QString &)), 
281
        supplementaryServicesIface.data(), SLOT(ConnectedLineRestrictionComplete(const QString &, const QString &)));
282
283
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(initiateFailed()), supplementaryServicesIface.data(), SLOT(InitiateFailed()));
284
285
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(stateChanged(const QString&)), supplementaryServicesIface.data(), SLOT(StateChanged(const QString&)));
286
67.2.3 by Tiago Salem Herrmann
add respondComplete() signal
287
    QObject::connect(mOfonoSupplementaryServices, SIGNAL(respondComplete(bool, const QString &)), supplementaryServicesIface.data(), SLOT(RespondComplete(bool, const QString &)));
288
149.3.1 by Tiago Salem Herrmann
- Improve oFonoConnection cleanup
289
    QObject::connect(this, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
34.2.4 by Tiago Salem Herrmann
fix comment
290
    // workaround: we can't add services here as tp-ofono interfaces are not exposed on dbus
291
    // todo: use QDBusServiceWatcher
34.2.1 by Tiago Salem Herrmann
add initial mms support
292
    QTimer::singleShot(1000, this, SLOT(onCheckMMSServices()));
293
}
294
149.3.1 by Tiago Salem Herrmann
- Improve oFonoConnection cleanup
295
void oFonoConnection::onDisconnected()
296
{
297
    setStatus(Tp::ConnectionStatusDisconnected, Tp::ConnectionStatusReasonRequested);
298
}
299
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
300
QMap<QString, oFonoCallChannel*> oFonoConnection::callChannels()
301
{
302
    return mCallChannels;
303
}
304
34.2.1 by Tiago Salem Herrmann
add initial mms support
305
void oFonoConnection::onCheckMMSServices()
306
{
307
    Q_FOREACH(QString servicePath, mMmsdManager->services()) {
308
        onMMSDServiceAdded(servicePath);
309
    }
310
}
311
149.4.10 by Tiago Salem Herrmann
Also use SimManager interface to retrieve mobile country code
312
void oFonoConnection::updateMcc()
149.4.9 by Tiago Salem Herrmann
Set MCC in PhoneUtils when needed
313
{
149.4.10 by Tiago Salem Herrmann
Also use SimManager interface to retrieve mobile country code
314
    QString mcc;
315
    // check if the network mcc is available first, then try the sim card mcc
316
    if (!mOfonoNetworkRegistration->mcc().isEmpty()) {
317
        mcc = mOfonoNetworkRegistration->mcc();
318
    } else if (!mOfonoSimManager->mobileCountryCode().isEmpty()) {
319
        mcc = mOfonoSimManager->mobileCountryCode();
320
    }
149.4.9 by Tiago Salem Herrmann
Set MCC in PhoneUtils when needed
321
    PhoneUtils::setMcc(mcc);
322
    emergencyModeIface->setCountryCode(PhoneUtils::countryCodeForMCC(mcc));
323
}
324
34.2.1 by Tiago Salem Herrmann
add initial mms support
325
void oFonoConnection::onMMSDServiceAdded(const QString &path)
326
{
95.1.1 by Tiago Salem Herrmann
Check if the mms service matches the modem object path
327
    MMSDService *service = new MMSDService(path, this);
328
    if (service->modemObjectPath() != mModemPath) {
329
        service->deleteLater();
330
        return;
331
    }
34.2.1 by Tiago Salem Herrmann
add initial mms support
332
    qDebug() << "oFonoConnection::onMMSServiceAdded" << path;
333
    mMmsdServices[path] = service;
334
    QObject::connect(service, SIGNAL(messageAdded(const QString&, const QVariantMap&)), SLOT(onMMSAdded(const QString&, const QVariantMap&)));
335
    QObject::connect(service, SIGNAL(messageRemoved(const QString&)), SLOT(onMMSRemoved(const QString&)));
336
    Q_FOREACH(MessageStruct message, service->messages()) {
34.2.5 by Tiago Salem Herrmann
rename addMMStoService to addMMSToService
337
        addMMSToService(message.path.path(), message.properties, service->path());
34.2.1 by Tiago Salem Herrmann
add initial mms support
338
    }
339
}
340
77.2.1 by Tiago Salem Herrmann
add support for sending mms's
341
QDBusObjectPath oFonoConnection::sendMMS(const QStringList &numbers, const OutgoingAttachmentList& attachments)
342
{
77.2.6 by Tiago Salem Herrmann
check if service exist before using them
343
    // FIXME: dualsim: mms's for now will only be sent using the first modem
344
    if (mMmsdServices.count() > 0) {
77.2.1 by Tiago Salem Herrmann
add support for sending mms's
345
        return mMmsdServices.first()->sendMessage(numbers, attachments);
346
    }
347
    qDebug() << "No mms service available";
348
    return QDBusObjectPath();
349
}
350
34.2.1 by Tiago Salem Herrmann
add initial mms support
351
void oFonoConnection::onMMSDServiceRemoved(const QString &path)
352
{
353
    MMSDService *service = mMmsdServices.take(path);
354
    if (!service) {
34.2.7 by Tiago Salem Herrmann
use qWarning to report errors
355
        qWarning() << "oFonoConnection::onMMSServiceRemoved failed" << path;
34.2.1 by Tiago Salem Herrmann
add initial mms support
356
        return;
357
    }
358
359
    // remove all messages from this service
360
    Q_FOREACH(MMSDMessage *message, mServiceMMSList[service->path()]) {
361
        qDebug() << "removing message " <<  message->path() << " from service " << service->path();
362
        message->deleteLater();
363
        mServiceMMSList[service->path()].removeAll(message);
364
    }
365
    mServiceMMSList.remove(service->path());
366
    service->deleteLater();
367
    qDebug() << "oFonoConnection::onMMSServiceRemoved" << path;
368
}
369
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
370
oFonoTextChannel* oFonoConnection::textChannelForMembers(const QStringList &members)
371
{
372
    Q_FOREACH(oFonoTextChannel* channel, mTextChannels) {
373
        int count = 0;
60.2.5 by Tiago Salem Herrmann
improve performance and avoid checking for errors multiple times
374
        Tp::DBusError error;
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
375
        if (members.size() != channel->members().size()) {
376
            continue;
377
        }
60.2.5 by Tiago Salem Herrmann
improve performance and avoid checking for errors multiple times
378
        QStringList phoneNumbersOld = inspectHandles(Tp::HandleTypeContact, channel->members(), &error);
379
        if (error.isValid()) {
380
            continue;
381
        }
382
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
383
        Q_FOREACH(const QString &phoneNumberNew, members) {
60.2.5 by Tiago Salem Herrmann
improve performance and avoid checking for errors multiple times
384
            Q_FOREACH(const QString &phoneNumberOld, phoneNumbersOld) {
112.1.1 by Tiago Salem Herrmann
don't reuse handles
385
                if (PhoneUtils::normalizePhoneNumber(phoneNumberOld) == PhoneUtils::normalizePhoneNumber(phoneNumberNew)) {
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
386
                    count++;
387
                }
388
            }
389
        }
390
        if (count == members.size()) {
391
            return channel;
392
        }
393
    }
394
    return NULL;
395
}
396
34.2.5 by Tiago Salem Herrmann
rename addMMStoService to addMMSToService
397
void oFonoConnection::addMMSToService(const QString &path, const QVariantMap &properties, const QString &servicePath)
34.2.1 by Tiago Salem Herrmann
add initial mms support
398
{
34.2.5 by Tiago Salem Herrmann
rename addMMStoService to addMMSToService
399
    qDebug() << "addMMSToService " << path << properties << servicePath;
34.2.1 by Tiago Salem Herrmann
add initial mms support
400
    MMSDMessage *msg = new MMSDMessage(path, properties);
401
    mServiceMMSList[servicePath].append(msg);
402
    if (properties["Status"] ==  "received") {
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
403
        const QString senderNormalizedNumber = PhoneUtils::normalizePhoneNumber(properties["Sender"].toString());
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
404
        QStringList recipientList = properties["Recipients"].toStringList();
120.2.6 by Tiago Salem Herrmann
perform sanity check in the recipient list
405
        // remove empty strings if any
406
        recipientList.removeAll("");
120.2.3 by Tiago Salem Herrmann
remove own number from recipient list
407
        // remove ourselves from the recipient list 
408
        Q_FOREACH(const QString &myNumber, mOfonoSimManager->subscriberNumbers()) {
409
            Q_FOREACH(const QString &remoteNumber, recipientList) {
410
                if (PhoneUtils::comparePhoneNumbers(remoteNumber, myNumber)) {
411
                    recipientList.removeAll(remoteNumber);
412
                    break;
413
                }
414
            }
415
        }
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
416
        QSet<QString> recipients;
417
        Tp::UIntList initialInviteeHandles;
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
418
        Q_FOREACH(const QString &recipient, recipientList) {
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
419
            recipients << PhoneUtils::normalizePhoneNumber(recipient);
420
            initialInviteeHandles << ensureHandle(recipient);
421
        }
34.2.1 by Tiago Salem Herrmann
add initial mms support
422
        // check if there is an open channel for this number and use it
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
423
        oFonoTextChannel *channel = textChannelForMembers(QStringList() << senderNormalizedNumber << recipients.toList());
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
424
        if (channel) {
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
425
            channel->mmsReceived(path, ensureHandle(senderNormalizedNumber), properties);
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
426
            return;
34.2.1 by Tiago Salem Herrmann
add initial mms support
427
        }
428
429
        Tp::DBusError error;
430
        bool yours;
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
431
        QVariantMap request;
432
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
433
        uint handle = ensureHandle(senderNormalizedNumber);
434
        qDebug() << "ensure handle" << senderNormalizedNumber << handle;
435
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
436
        request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
437
        request[TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")] = handle;
438
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
439
        if (initialInviteeHandles.size() > 0) {
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
440
            initialInviteeHandles << handle;
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
441
            request[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")] = QVariant::fromValue(initialInviteeHandles);
442
            ensureChannel(request, yours, false, &error);
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
443
        } else {
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
444
            request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact;
445
            request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] = handle;
446
            ensureChannel(request, yours, false, &error);
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
447
        }
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
448
34.2.1 by Tiago Salem Herrmann
add initial mms support
449
        if(error.isValid()) {
34.2.6 by Tiago Salem Herrmann
change qDebugs to qCritical
450
            qCritical() << "Error creating channel for incoming message " << error.name() << error.message();
34.2.1 by Tiago Salem Herrmann
add initial mms support
451
            return;
452
        }
120.2.1 by Tiago Salem Herrmann
add initial support for mms group chat
453
        channel = textChannelForMembers(QStringList() << senderNormalizedNumber << recipients.toList());
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
454
        if (channel) {
120.2.2 by Tiago Salem Herrmann
remove own phone number from recipient list
455
            channel->mmsReceived(path, handle, properties);
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
456
        }
34.2.1 by Tiago Salem Herrmann
add initial mms support
457
    }
458
}
459
460
void oFonoConnection::onMMSAdded(const QString &path, const QVariantMap &properties)
461
{
462
    qDebug() << "oFonoConnection::onMMSAdded" << path << properties;
463
    MMSDService *service = qobject_cast<MMSDService*>(sender());
464
    if (!service) {
34.2.7 by Tiago Salem Herrmann
use qWarning to report errors
465
        qWarning() << "oFonoConnection::onMMSAdded failed";
34.2.1 by Tiago Salem Herrmann
add initial mms support
466
        return;
467
    }
468
34.2.5 by Tiago Salem Herrmann
rename addMMStoService to addMMSToService
469
    addMMSToService(path, properties, service->path());
34.2.1 by Tiago Salem Herrmann
add initial mms support
470
}
471
472
void oFonoConnection::onMMSRemoved(const QString &path)
473
{
474
    qDebug() << "oFonoConnection::onMMSRemoved" << path;
475
    MMSDService *service = qobject_cast<MMSDService*>(sender());
476
    if (!service) {
34.2.7 by Tiago Salem Herrmann
use qWarning to report errors
477
        qWarning() << "oFonoConnection::onMMSRemoved failed";
34.2.1 by Tiago Salem Herrmann
add initial mms support
478
        return;
479
    }
480
481
    // remove this message from the service
482
    Q_FOREACH(MMSDMessage *message, mServiceMMSList[service->path()]) {
483
        if (message->path() == path) {
484
            message->deleteLater();
485
            mServiceMMSList[service->path()].removeAll(message);
486
            break;
487
        }
488
    }
7 by Tiago Salem Herrmann
add online presence support
489
}
490
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
491
oFonoConnection::~oFonoConnection() {
149.3.1 by Tiago Salem Herrmann
- Improve oFonoConnection cleanup
492
    dbusConnection().unregisterObject(objectPath(), QDBusConnection::UnregisterTree);
493
    dbusConnection().unregisterService(busName());
494
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
495
    mOfonoModemManager->deleteLater();
496
    mOfonoMessageManager->deleteLater();
497
    mOfonoVoiceCallManager->deleteLater();
498
    mOfonoCallVolume->deleteLater();
149.3.1 by Tiago Salem Herrmann
- Improve oFonoConnection cleanup
499
    mOfonoMessageWaiting->deleteLater();
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
500
    mOfonoNetworkRegistration->deleteLater();
149.3.1 by Tiago Salem Herrmann
- Improve oFonoConnection cleanup
501
    mOfonoSupplementaryServices->deleteLater();
502
    mOfonoSimManager->deleteLater();
503
    mMmsdManager->deleteLater();
504
 
34.2.1 by Tiago Salem Herrmann
add initial mms support
505
    Q_FOREACH(MMSDService *service, mMmsdServices) {
506
        onMMSDServiceRemoved(service->path());
507
    }
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
508
}
509
7 by Tiago Salem Herrmann
add online presence support
510
bool oFonoConnection::isNetworkRegistered()
511
{
512
    QString status = mOfonoNetworkRegistration->status();
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
513
    if (!mOfonoNetworkRegistration->isValid()) {
514
        return false;
515
    }
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
516
    return  !(!mOfonoModem->isValid() ||
517
              !mOfonoModem->online() ||
7 by Tiago Salem Herrmann
add online presence support
518
              status == "unregistered" ||
519
              status == "denied" ||
520
              status == "unknown" ||
521
              status == "searching" ||
522
              status.isEmpty());
523
}
524
525
uint oFonoConnection::setPresence(const QString& status, const QString& statusMessage, Tp::DBusError *error)
526
{
527
    qDebug() << "setPresence" << status;
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
528
    // this prevents tp-qt to propagate the available status
529
    error->set(TP_QT_ERROR_NOT_AVAILABLE, "Can't change online status: Operation not supported");
7 by Tiago Salem Herrmann
add online presence support
530
    return selfHandle();
531
}
532
533
Tp::ContactAttributesMap oFonoConnection::getContactAttributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error)
534
{
535
    qDebug() << "getContactAttributes" << handles << ifaces;
536
    Tp::ContactAttributesMap attributesMap;
537
    QVariantMap attributes;
538
    Q_FOREACH(uint handle, handles) {
91.2.1 by Tiago Salem Herrmann
check if the returned value is valid to avoid crashes
539
        QStringList inspectedHandles = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error);
540
        if (inspectedHandles.size() > 0) {
541
            attributes[TP_QT_IFACE_CONNECTION+"/contact-id"] = inspectedHandles.at(0);
542
        } else {
543
            continue;
544
        }
7 by Tiago Salem Herrmann
add online presence support
545
        if (ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) {
546
            attributes[TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE+"/presence"] = QVariant::fromValue(mSelfPresence);
547
        }
548
        attributesMap[handle] = attributes;
549
    }
550
    return attributesMap;
551
}
552
553
void oFonoConnection::onValidityChanged(bool valid)
554
{
95.2.5 by Tiago Salem Herrmann
- refresh properties when interfaces become available
555
    // WORKAROUND: ofono-qt does not refresh the properties once the interface
556
    // becomes available, so it contains old values.
116.1.3 by Tiago Salem Herrmann
only refresh interfaces that changed
557
    if (sender() == mOfonoSimManager) {
558
        Q_EMIT mOfonoSimManager->modem()->pathChanged(mOfonoModem->path());
559
    } else if (sender() == mOfonoNetworkRegistration) {
560
        Q_EMIT mOfonoNetworkRegistration->modem()->pathChanged(mOfonoModem->path());
561
    } else if (sender() == mOfonoVoiceCallManager) {
562
        Q_EMIT mOfonoVoiceCallManager->modem()->pathChanged(mOfonoModem->path());
563
    }
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
564
    QString modemSerial;
565
    if (valid) {
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
566
        modemSerial = mOfonoModem->serial();
7 by Tiago Salem Herrmann
add online presence support
567
    }
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
568
    supplementaryServicesIface->setSerial(modemSerial);
107.4.1 by Tiago Salem Herrmann
refresh emergency numbers when appropriate
569
    emergencyModeIface->setEmergencyNumbers(mOfonoVoiceCallManager->emergencyNumbers());
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
570
    updateOnlineStatus();
7 by Tiago Salem Herrmann
add online presence support
571
}
572
95.2.1 by Tiago Salem Herrmann
report away status if there is no network and offline if the sim card is not present
573
void oFonoConnection::updateOnlineStatus()
7 by Tiago Salem Herrmann
add online presence support
574
{
575
    Tp::SimpleContactPresences presences;
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
576
    mSelfPresence.statusMessage = "";
577
    mSelfPresence.type = Tp::ConnectionPresenceTypeOffline;
120.2.7 by Tiago Salem Herrmann
change selfHandle when the actual phone number is retrieved
578
    Tp::DBusError *error;
579
    QString selfHandleId = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << selfHandle(), error)[0];
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
580
95.2.5 by Tiago Salem Herrmann
- refresh properties when interfaces become available
581
    if (!mOfonoModem->isValid()) {
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
582
        mSelfPresence.status = "nomodem";
583
    } else if (!mOfonoModem->online()) {
584
        mSelfPresence.status = "flightmode";
95.2.5 by Tiago Salem Herrmann
- refresh properties when interfaces become available
585
    } else if ((mOfonoSimManager->isValid() && !mOfonoSimManager->present()) ||
586
                !mOfonoSimManager->isValid()) {
95.2.4 by Tiago Salem Herrmann
report new status: nomodem, nosim, flightmode, and all ofono network status
587
        mSelfPresence.status = "nosim";
116.1.1 by Tiago Salem Herrmann
check if the SimManager interface is available and property not null
588
    } else if (mOfonoSimManager->isValid() && mOfonoSimManager->present() && 
589
               mOfonoSimManager->pinRequired() != "none" && !mOfonoSimManager->pinRequired().isEmpty()) {
107.3.1 by Tiago Salem Herrmann
report away status when sim is locked
590
        mSelfPresence.status = "simlocked";
591
        mSelfPresence.type = Tp::ConnectionPresenceTypeAway;
95.2.5 by Tiago Salem Herrmann
- refresh properties when interfaces become available
592
    } else if (isNetworkRegistered()) {
593
        mSelfPresence.status = mOfonoNetworkRegistration->status();
594
        mSelfPresence.statusMessage = mOfonoNetworkRegistration->name();
595
        mSelfPresence.type = Tp::ConnectionPresenceTypeAvailable;
596
    } else {
597
        mSelfPresence.status = mOfonoNetworkRegistration->status();
598
        mSelfPresence.type = Tp::ConnectionPresenceTypeAway;
7 by Tiago Salem Herrmann
add online presence support
599
    }
120.2.7 by Tiago Salem Herrmann
change selfHandle when the actual phone number is retrieved
600
601
    if (mOfonoSimManager->subscriberNumbers().size() > 0 && selfHandleId != mOfonoSimManager->subscriberNumbers()[0]) {
602
        setSelfHandle(newHandle(mOfonoSimManager->subscriberNumbers()[0]));
603
    }
604
7 by Tiago Salem Herrmann
add online presence support
605
    presences[selfHandle()] = mSelfPresence;
606
    simplePresenceIface->setPresences(presences);
149.4.10 by Tiago Salem Herrmann
Also use SimManager interface to retrieve mobile country code
607
608
    updateMcc();
1 by Tiago Salem Herrmann
initial commit
609
}
610
611
uint oFonoConnection::newHandle(const QString &identifier)
612
{
613
    mHandles[++mHandleCount] = identifier;
614
    return mHandleCount;
615
}
616
617
QStringList oFonoConnection::inspectHandles(uint handleType, const Tp::UIntList& handles, Tp::DBusError *error)
618
{
619
    QStringList identifiers;
620
621
    if( handleType != Tp::HandleTypeContact ) {
622
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,"Not supported");
623
        return QStringList();
624
    }
625
626
    qDebug() << "oFonoConnection::inspectHandles " << handles;
627
    Q_FOREACH( uint handle, handles) {
628
        if (mHandles.keys().contains(handle)) {
629
            identifiers.append(mHandles.value(handle));
630
        } else {
631
            error->set(TP_QT_ERROR_INVALID_HANDLE, "Handle not found");
632
            return QStringList();
633
        }
634
    }
2 by Tiago Salem Herrmann
- add call channel support
635
    qDebug() << "oFonoConnection::inspectHandles " << identifiers;
1 by Tiago Salem Herrmann
initial commit
636
    return identifiers;
637
}
638
639
void oFonoConnection::connect(Tp::DBusError *error) {
640
    qDebug() << "oFonoConnection::connect";
641
    setStatus(Tp::ConnectionStatusConnected, Tp::ConnectionStatusReasonRequested);
642
}
643
644
Tp::UIntList oFonoConnection::requestHandles(uint handleType, const QStringList& identifiers, Tp::DBusError* error)
645
{
2 by Tiago Salem Herrmann
- add call channel support
646
    qDebug() << "requestHandles";
1 by Tiago Salem Herrmann
initial commit
647
    Tp::UIntList handles;
648
649
    if( handleType != Tp::HandleTypeContact ) {
650
        error->set(TP_QT_ERROR_INVALID_ARGUMENT, "Not supported");
651
        return Tp::UIntList();
652
    }
653
654
    Q_FOREACH( const QString& identifier, identifiers) {
51.1.3 by Tiago Salem Herrmann
add PhoneUtils class
655
        const QString normalizedNumber = PhoneUtils::normalizePhoneNumber(identifier);
1 by Tiago Salem Herrmann
initial commit
656
        if (mHandles.values().contains(normalizedNumber)) {
657
            handles.append(mHandles.key(normalizedNumber));
51.1.3 by Tiago Salem Herrmann
add PhoneUtils class
658
        } else if (PhoneUtils::isPhoneNumber(normalizedNumber)) {
1 by Tiago Salem Herrmann
initial commit
659
            handles.append(newHandle(normalizedNumber));
660
        } else {
51.1.1 by Tiago Salem Herrmann
accept non numeric ids
661
            handles.append(newHandle(identifier));
1 by Tiago Salem Herrmann
initial commit
662
        }
663
    }
2 by Tiago Salem Herrmann
- add call channel support
664
    qDebug() << "requestHandles" << handles;
1 by Tiago Salem Herrmann
initial commit
665
    return handles;
666
}
667
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
668
Tp::BaseChannelPtr oFonoConnection::createTextChannel(const QVariantMap &request, Tp::DBusError *error)
5 by Tiago Salem Herrmann
- rename some methods
669
{
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
670
    uint targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt();
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
671
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
672
    if (mSelfPresence.type != Tp::ConnectionPresenceTypeAvailable) {
673
        error->set(TP_QT_ERROR_NETWORK_ERROR, "No network available");
674
        return Tp::BaseChannelPtr();
675
    }
676
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
677
    QStringList phoneNumbers;
60.4.2 by Tiago Salem Herrmann
add class 0 sms support
678
    bool flash = false;
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
679
    if (request.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"))) {
680
        phoneNumbers << inspectHandles(Tp::HandleTypeContact, qdbus_cast<Tp::UIntList>(request[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")]), error);
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
681
    } else {
682
        phoneNumbers << mHandles.value(targetHandle);
5 by Tiago Salem Herrmann
- rename some methods
683
    }
684
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
685
    if (request.contains(TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash"))) {
686
        flash = request[TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash")].toBool();
60.4.2 by Tiago Salem Herrmann
add class 0 sms support
687
    }
688
689
    oFonoTextChannel *channel = new oFonoTextChannel(this, phoneNumbers, flash);
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
690
    mTextChannels << channel;
691
    QObject::connect(channel, SIGNAL(messageRead(QString)), SLOT(onMessageRead(QString)));
692
    QObject::connect(channel, SIGNAL(destroyed()), SLOT(onTextChannelClosed()));
693
    return channel->baseChannel();
5 by Tiago Salem Herrmann
- rename some methods
694
}
695
34.2.1 by Tiago Salem Herrmann
add initial mms support
696
void oFonoConnection::onMessageRead(const QString &id)
697
{
698
    Q_FOREACH(QList<MMSDMessage*> messages, mServiceMMSList.values()) {
699
        Q_FOREACH(MMSDMessage* message, messages) {
700
            if (message->path() == id) {
701
                message->markRead();
702
                message->remove();
703
                return;
704
            }
705
        }
706
    }
707
}
708
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
709
void oFonoConnection::onConferenceCallChannelClosed()
710
{
711
    if (mConferenceCall) {
712
        mConferenceCall = NULL;
713
    }
714
}
715
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
716
Tp::BaseChannelPtr oFonoConnection::createCallChannel(const QVariantMap &request, Tp::DBusError *error)
5 by Tiago Salem Herrmann
- rename some methods
717
{
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
718
    uint targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt();
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
719
    uint initiatorHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")).toUInt();
5 by Tiago Salem Herrmann
- rename some methods
720
16 by Tiago Salem Herrmann
check errors on dial() and sendMessage()
721
    bool success = true;
5 by Tiago Salem Herrmann
- rename some methods
722
    QString newPhoneNumber = mHandles.value(targetHandle);
82.1.3 by Gustavo Pichorim Boiko
Fix wrong condition.
723
    bool available = (mSelfPresence.type == Tp::ConnectionPresenceTypeAvailable);
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
724
    bool isConference = (request.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialChannels")) &&
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
725
                         (!request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")) || request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] == Tp::HandleTypeNone) &&
726
                         (!request.contains(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")) || request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] == 0));
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
727
149.4.14 by Tiago Salem Herrmann
Don't check for emergency numbers. This check must be done by the upper layers. We simply bypass the request to ofono
728
    if (!available && isConference) {
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
729
        error->set(TP_QT_ERROR_NETWORK_ERROR, "No network available");
730
        return Tp::BaseChannelPtr();
731
    }
732
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
733
    if (initiatorHandle == 0 && targetHandle != selfHandle()) {
734
        initiatorHandle = selfHandle();
735
    }
736
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
737
    if (isConference) {
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
738
        // conference call request
739
        if (mConferenceCall) {
740
            error->set(TP_QT_ERROR_NOT_AVAILABLE, "Conference call already exists");
741
            return Tp::BaseChannelPtr();
742
        }
82.1.2 by Gustavo Pichorim Boiko
Make it possible to dial emergency numbers even when the presence is not Available.
743
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
744
        QList<QDBusObjectPath> channels = mOfonoVoiceCallManager->createMultiparty();
745
        if (!channels.isEmpty()) {
746
            mConferenceCall = new oFonoConferenceCallChannel(this);
747
            QObject::connect(mConferenceCall, SIGNAL(destroyed()), SLOT(onConferenceCallChannelClosed()));
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
748
            mConferenceCall->baseChannel()->setInitiatorHandle(initiatorHandle);
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
749
            return mConferenceCall->baseChannel();
750
        }
60.3.3 by Tiago Salem Herrmann
remove call content for conference channels
751
        error->set(TP_QT_ERROR_NOT_AVAILABLE, "Impossible to merge calls");
752
        return Tp::BaseChannelPtr();
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
753
    }
754
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
755
    QDBusObjectPath objpath(request["ofonoObjPath"].toString());
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
756
757
    if (objpath.path().isEmpty()) {
16 by Tiago Salem Herrmann
check errors on dial() and sendMessage()
758
        objpath = mOfonoVoiceCallManager->dial(newPhoneNumber, "", success);
5 by Tiago Salem Herrmann
- rename some methods
759
    }
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
760
16 by Tiago Salem Herrmann
check errors on dial() and sendMessage()
761
    qDebug() << "success " << success;
762
    if (objpath.path().isEmpty() || !success) {
763
        if (!success) {
764
            error->set(TP_QT_ERROR_NOT_AVAILABLE, mOfonoVoiceCallManager->errorMessage());
765
        } else {
766
            error->set(TP_QT_ERROR_NOT_AVAILABLE, "Channel could not be created");
767
        }
5 by Tiago Salem Herrmann
- rename some methods
768
        return Tp::BaseChannelPtr();
769
    }
770
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
771
    oFonoCallChannel *channel = new oFonoCallChannel(this, newPhoneNumber, targetHandle, objpath.path());
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
772
    channel->baseChannel()->setInitiatorHandle(initiatorHandle);
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
773
    mCallChannels[objpath.path()] = channel;
60.3.5 by Tiago Salem Herrmann
add tests for conference calls
774
    QObject::connect(channel, SIGNAL(destroyed()), SLOT(onCallChannelDestroyed()));
775
    QObject::connect(channel, SIGNAL(closed()), SLOT(onCallChannelClosed()));
60.3.4 by Tiago Salem Herrmann
handle conference call status (active/on hold)
776
    QObject::connect(channel, SIGNAL(merged()), SLOT(onCallChannelMerged()));
777
    QObject::connect(channel, SIGNAL(splitted()), SLOT(onCallChannelSplitted()));
778
    QObject::connect(channel, SIGNAL(multipartyCallHeld()), SLOT(onMultipartyCallHeld()));
779
    QObject::connect(channel, SIGNAL(multipartyCallActive()), SLOT(onMultipartyCallActive()));
780
    qDebug() << channel;
781
    return channel->baseChannel();
782
}
783
784
void oFonoConnection::onMultipartyCallHeld()
785
{
786
    if (!mConferenceCall) {
787
        return;
788
    }
789
790
    mConferenceCall->setConferenceActive(false);
791
}
792
793
void oFonoConnection::onMultipartyCallActive()
794
{
795
    if (!mConferenceCall) {
796
        return;
797
    }
798
799
    mConferenceCall->setConferenceActive(true);
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
800
}
801
802
void oFonoConnection::onCallChannelMerged()
803
{
804
    if (!mConferenceCall) {
805
        return;
806
    }
807
    oFonoCallChannel *channel = static_cast<oFonoCallChannel*>(sender());
60.3.5 by Tiago Salem Herrmann
add tests for conference calls
808
    Q_EMIT channelMerged(QDBusObjectPath(channel->baseChannel()->objectPath()));
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
809
}
810
811
void oFonoConnection::onCallChannelSplitted()
812
{
813
    if (!mConferenceCall) {
814
        return;
815
    }
816
    oFonoCallChannel *channel = static_cast<oFonoCallChannel*>(sender());
60.3.5 by Tiago Salem Herrmann
add tests for conference calls
817
    Q_EMIT channelSplitted(QDBusObjectPath(channel->baseChannel()->objectPath()));
60.3.1 by Tiago Salem Herrmann
add initial multi party call support
818
}
819
5 by Tiago Salem Herrmann
- rename some methods
820
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
821
Tp::BaseChannelPtr oFonoConnection::createChannel(const QVariantMap &request, Tp::DBusError *error)
1 by Tiago Salem Herrmann
initial commit
822
{
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
823
    const QString channelType = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")).toString();
824
5 by Tiago Salem Herrmann
- rename some methods
825
    if (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT) {
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
826
        return createTextChannel(request, error);
5 by Tiago Salem Herrmann
- rename some methods
827
    } else if (channelType == TP_QT_IFACE_CHANNEL_TYPE_CALL) {
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
828
        return createCallChannel(request, error);
5 by Tiago Salem Herrmann
- rename some methods
829
    } else {
1 by Tiago Salem Herrmann
initial commit
830
        error->set(TP_QT_ERROR_NOT_IMPLEMENTED, "Channel type not available");
831
    }
832
833
    return Tp::BaseChannelPtr();
834
}
835
2 by Tiago Salem Herrmann
- add call channel support
836
OfonoMessageManager *oFonoConnection::messageManager()
1 by Tiago Salem Herrmann
initial commit
837
{
838
    return mOfonoMessageManager;
839
}
840
2 by Tiago Salem Herrmann
- add call channel support
841
OfonoVoiceCallManager *oFonoConnection::voiceCallManager()
1 by Tiago Salem Herrmann
initial commit
842
{
843
    return mOfonoVoiceCallManager;
844
}
845
2 by Tiago Salem Herrmann
- add call channel support
846
OfonoCallVolume *oFonoConnection::callVolume()
847
{
848
    return mOfonoCallVolume;
849
}
850
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
851
void oFonoConnection::onDeliveryReportReceived(const QString &messageId, const QVariantMap& info)
852
{
55.2.3 by Tiago Salem Herrmann
move database methods to a separate class: PendingMessagesManager
853
    const QString pendingMessageNumber = PendingMessagesManager::instance()->recipientIdForMessageId(messageId);
854
    if (pendingMessageNumber.isEmpty()) {
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
855
        return;
856
    }
55.2.3 by Tiago Salem Herrmann
move database methods to a separate class: PendingMessagesManager
857
    const QString normalizedNumber = PhoneUtils::normalizePhoneNumber(pendingMessageNumber);
858
    PendingMessagesManager::instance()->removePendingMessage(messageId);
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
859
    // check if there is an open channel for this sender and use it
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
860
861
    oFonoTextChannel *channel = textChannelForMembers(QStringList() << normalizedNumber);
862
    if(channel) {
863
        channel->deliveryReportReceived(messageId, ensureHandle(normalizedNumber), info["Delivered"].toBool());
864
        return;
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
865
    }
866
867
    Tp::DBusError error;
868
    bool yours;
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
869
    uint handle = ensureHandle(normalizedNumber);
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
870
871
    QVariantMap request;
872
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
873
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact;
874
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] = handle;
875
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")] = handle;
876
877
    ensureChannel(request, yours, false, &error);
878
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
879
    if(error.isValid()) {
880
        qWarning() << "Error creating channel for incoming message" << error.name() << error.message();
881
        return;
882
    }
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
883
    channel = textChannelForMembers(QStringList() << normalizedNumber);
884
    if(channel) {
885
        channel->deliveryReportReceived(messageId, ensureHandle(normalizedNumber), info["Delivered"].toBool());
886
        return;
887
    }
55.2.1 by Tiago Salem Herrmann
add support for delivery reports
888
}
889
5 by Tiago Salem Herrmann
- rename some methods
890
void oFonoConnection::onOfonoIncomingMessage(const QString &message, const QVariantMap &info)
1 by Tiago Salem Herrmann
initial commit
891
{
60.4.2 by Tiago Salem Herrmann
add class 0 sms support
892
    ensureTextChannel(message, info, false);
893
}
894
895
void oFonoConnection::onOfonoImmediateMessage(const QString &message, const QVariantMap &info)
896
{
897
    ensureTextChannel(message, info, true);
898
}
899
900
void oFonoConnection::ensureTextChannel(const QString &message, const QVariantMap &info, bool flash)
901
{
51.1.3 by Tiago Salem Herrmann
add PhoneUtils class
902
    const QString normalizedNumber = PhoneUtils::normalizePhoneNumber(info["Sender"].toString());
51.1.1 by Tiago Salem Herrmann
accept non numeric ids
903
    // check if there is an open channel for this sender and use it
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
904
    oFonoTextChannel *channel = textChannelForMembers(QStringList() << normalizedNumber);
905
    if(channel) {
906
        channel->messageReceived(message, ensureHandle(normalizedNumber), info);
907
        return;
1 by Tiago Salem Herrmann
initial commit
908
    }
909
910
    Tp::DBusError error;
911
    bool yours;
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
912
    uint handle = ensureHandle(normalizedNumber);
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
913
    QVariantMap request;
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
914
    request[TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash")] = flash;
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
915
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_TEXT;
916
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact;
917
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] = handle;
918
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")] = handle;
919
920
    ensureChannel(request, yours, false, &error);
1 by Tiago Salem Herrmann
initial commit
921
    if(error.isValid()) {
34.2.7 by Tiago Salem Herrmann
use qWarning to report errors
922
        qWarning() << "Error creating channel for incoming message" << error.name() << error.message();
1 by Tiago Salem Herrmann
initial commit
923
        return;
924
    }
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
925
926
    channel = textChannelForMembers(QStringList() << normalizedNumber);
927
    if (channel) {
928
        channel->messageReceived(message, ensureHandle(normalizedNumber), info);
929
    }
1 by Tiago Salem Herrmann
initial commit
930
}
931
932
void oFonoConnection::onTextChannelClosed()
933
{
934
    oFonoTextChannel *channel = static_cast<oFonoTextChannel*>(sender());
935
    if (channel) {
60.2.2 by Tiago Salem Herrmann
adapt ensureChannel to match the new tp-qt api
936
        qDebug() << "text channel closed";
937
        mTextChannels.removeAll(channel);
1 by Tiago Salem Herrmann
initial commit
938
    }
939
}
940
2 by Tiago Salem Herrmann
- add call channel support
941
void oFonoConnection::onCallChannelClosed()
942
{
943
    qDebug() << "onCallChannelClosed()";
944
    oFonoCallChannel *channel = static_cast<oFonoCallChannel*>(sender());
945
    if (channel) {
60.3.5 by Tiago Salem Herrmann
add tests for conference calls
946
        Q_EMIT channelHangup(QDBusObjectPath(channel->baseChannel()->objectPath()));
947
    }
948
}
949
950
951
void oFonoConnection::onCallChannelDestroyed()
952
{
953
    qDebug() << "onCallChannelDestroyed()";
954
    oFonoCallChannel *channel = static_cast<oFonoCallChannel*>(sender());
955
    if (channel) {
2 by Tiago Salem Herrmann
- add call channel support
956
        QString key = mCallChannels.key(channel);
957
        qDebug() << "call channel closed for number " << key;
958
        mCallChannels.remove(key);
959
    }
960
}
961
962
uint oFonoConnection::ensureHandle(const QString &phoneNumber)
963
{
51.1.3 by Tiago Salem Herrmann
add PhoneUtils class
964
    const QString normalizedNumber = PhoneUtils::normalizePhoneNumber(phoneNumber);
2 by Tiago Salem Herrmann
- add call channel support
965
966
    Q_FOREACH(const QString &phone, mHandles.values()) {
112.1.1 by Tiago Salem Herrmann
don't reuse handles
967
        if (normalizedNumber == phone) {
2 by Tiago Salem Herrmann
- add call channel support
968
            // this user already exists
969
            return mHandles.key(phone);
970
        }
971
    }
972
    return newHandle(normalizedNumber);
973
}
974
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
975
bool oFonoConnection::matchChannel(const Tp::BaseChannelPtr &channel, const QVariantMap &request, Tp::DBusError *error)
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
976
{
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
977
    QString channelType = request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")].toString();
978
    uint targetHandleType = request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")].toUInt();
979
    uint targetHandle = request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")].toUInt();
980
981
    if (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT &&
982
            channel->targetHandleType() == targetHandleType &&
983
            channel->targetHandle() == targetHandle &&
984
            targetHandleType == Tp::HandleTypeNone) {
985
        // check invitee handles
986
        if (request.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"))) {
987
            QStringList phoneNumbers = inspectHandles(Tp::HandleTypeContact, request[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")].value<Tp::UIntList>(), error);
988
            oFonoTextChannel *existingChannel = textChannelForMembers(phoneNumbers);
989
            return existingChannel && (channel == existingChannel->baseChannel());
990
        }
991
    }
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
992
    // we only match text channels
143.2.2 by Tiago Salem Herrmann
- Check for mms group chats
993
    return (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT) && BaseConnection::matchChannel(channel, request, error);
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
994
}
995
5 by Tiago Salem Herrmann
- rename some methods
996
void oFonoConnection::onOfonoCallAdded(const QString &call, const QVariantMap &properties)
1 by Tiago Salem Herrmann
initial commit
997
{
2 by Tiago Salem Herrmann
- add call channel support
998
    qDebug() << "new call" << call << properties;
999
1000
    bool yours;
1001
    Tp::DBusError error;
52.2.1 by Tiago Salem Herrmann
add support for private and unknown numbers
1002
    QString lineIdentification = properties["LineIdentification"].toString();
60.4.1 by Tiago Salem Herrmann
use ofono dbus object path to track calls
1003
1004
    // check if there is an open channel for this call, if so, ignore it
1005
    if (mCallChannels.keys().contains(call)) {
1006
        qWarning() << "call channel for this object path already exists: " << call;
1007
        return;
1008
    }
1009
52.2.1 by Tiago Salem Herrmann
add support for private and unknown numbers
1010
    QString normalizedNumber;
1011
    // TODO check if more than one private/unknown calls are supported at the same time
1012
    if (lineIdentification.isEmpty()) {
1013
        // unknown caller Id
1014
        lineIdentification = QString("x-ofono-unknown");
1015
        normalizedNumber = lineIdentification;
1016
    } else if (lineIdentification == "withheld") {
1017
        // private caller
1018
        lineIdentification = QString("x-ofono-private");
1019
        normalizedNumber = lineIdentification;
1020
    } else {
1021
        normalizedNumber = PhoneUtils::normalizePhoneNumber(lineIdentification);
1022
    }
2 by Tiago Salem Herrmann
- add call channel support
1023
1024
    uint handle = ensureHandle(normalizedNumber);
1025
    uint initiatorHandle = 0;
1026
    if (properties["State"] == "incoming" || properties["State"] == "waiting") {
1027
        initiatorHandle = handle;
1028
    } else {
1029
        initiatorHandle = selfHandle();
1030
    }
1031
1032
    qDebug() << "initiatorHandle " <<initiatorHandle;
1033
    qDebug() << "handle" << handle;
1034
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
1035
    QVariantMap request;
1036
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")] = TP_QT_IFACE_CHANNEL_TYPE_CALL;
1037
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")] = Tp::HandleTypeContact;
1038
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")] = handle;
1039
    request[TP_QT_IFACE_CHANNEL + QLatin1String(".InitiatorHandle")] = initiatorHandle;
1040
    request["ofonoObjPath"] = call;
1041
160.1.3 by Tiago Salem Herrmann
revert wrong change
1042
    Tp::BaseChannelPtr channel = ensureChannel(request, yours, false, &error);
137.3.1 by Alexandr Akulich
Fixed build on TelepathyQt-0.9.6.
1043
2 by Tiago Salem Herrmann
- add call channel support
1044
    if (error.isValid() || channel.isNull()) {
34.2.7 by Tiago Salem Herrmann
use qWarning to report errors
1045
        qWarning() << "error creating the channel " << error.name() << error.message();
2 by Tiago Salem Herrmann
- add call channel support
1046
        return;
1047
    }
1 by Tiago Salem Herrmann
initial commit
1048
}
8 by Tiago Salem Herrmann
- add presence interface (and connect it to ofono NetworkRegistration interface)
1049
1050
uint oFonoConnection::voicemailCount(Tp::DBusError *error)
1051
{
1052
    return mOfonoMessageWaiting->voicemailMessageCount();
1053
}
1054
1055
QString oFonoConnection::voicemailNumber(Tp::DBusError *error)
1056
{
1057
    return mOfonoMessageWaiting->voicemailMailboxNumber();
1058
}
1059
1060
bool oFonoConnection::voicemailIndicator(Tp::DBusError *error)
1061
{
1062
    return mOfonoMessageWaiting->voicemailWaiting();
1063
}
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
1064
91.3.2 by Tiago Salem Herrmann
move SpeakerInterface to AudioOutputsInterface
1065
QString oFonoConnection::activeAudioOutput()
1066
{
1067
    return mActiveAudioOutput;
1068
}
1069
1070
AudioOutputList oFonoConnection::audioOutputs()
1071
{
1072
    return mAudioOutputs;
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
1073
}
1074
82.1.1 by Gustavo Pichorim Boiko
Expose the emergency numbers via DBus to clients.
1075
QStringList oFonoConnection::emergencyNumbers(Tp::DBusError *error)
1076
{
1077
    return mOfonoVoiceCallManager->emergencyNumbers();
1078
}
1079
91.3.2 by Tiago Salem Herrmann
move SpeakerInterface to AudioOutputsInterface
1080
void oFonoConnection::setActiveAudioOutput(const QString &id)
1081
{
91.3.3 by Tiago Salem Herrmann
fake outputs for now
1082
    mActiveAudioOutput = id;
1083
    Q_EMIT activeAudioOutputChanged(id);
91.3.2 by Tiago Salem Herrmann
move SpeakerInterface to AudioOutputsInterface
1084
}
1085
67.2.1 by Tiago Salem Herrmann
add initial ussd support
1086
void oFonoConnection::USSDInitiate(const QString &command, Tp::DBusError *error)
1087
{
1088
    mOfonoSupplementaryServices->initiate(command);
1089
}
1090
1091
void oFonoConnection::USSDRespond(const QString &reply, Tp::DBusError *error)
1092
{
1093
    mOfonoSupplementaryServices->respond(reply);
1094
}
1095
1096
void oFonoConnection::USSDCancel(Tp::DBusError *error)
1097
{
1098
    mOfonoSupplementaryServices->cancel();
1099
}
1100
101.1.1 by Ricardo Salveti de Araujo
Improve event handling from pulse, also exporting mode changes.
1101
#ifdef USE_PULSEAUDIO
1102
void oFonoConnection::onAudioModeChanged(AudioMode mode)
1103
{
1104
    qDebug("PulseAudio audio mode changed: 0x%x", mode);
1105
120.1.1 by Tiago Salem Herrmann
disable proximity sensor also when using a wired headset
1106
    if (mode == AudioModeEarpiece && mActiveAudioOutput != "earpiece") {
1107
        setActiveAudioOutput("earpiece");
1108
    } else if (mode == AudioModeWiredHeadset && mActiveAudioOutput != "wired_headset") {
1109
        setActiveAudioOutput("wired_headset");
101.1.2 by Tiago Salem Herrmann
Hook qpulseaudioengine to the new AudioOutputs interface
1110
    } else if (mode == AudioModeSpeaker && mActiveAudioOutput != "speaker") {
1111
        setActiveAudioOutput("speaker");
1112
    } else if (mode == AudioModeBluetooth && mActiveAudioOutput != "bluetooth") {
1113
        setActiveAudioOutput("bluetooth");
101.1.1 by Ricardo Salveti de Araujo
Improve event handling from pulse, also exporting mode changes.
1114
    }
1115
}
1116
1117
void oFonoConnection::onAvailableAudioModesChanged(AudioModes modes)
1118
{
1119
    qDebug("PulseAudio available audio modes changed");
101.1.2 by Tiago Salem Herrmann
Hook qpulseaudioengine to the new AudioOutputs interface
1120
    bool defaultFound = false;
1121
    mAudioOutputs.clear();
1122
    Q_FOREACH(const AudioMode &mode, modes) {
1123
        AudioOutput output;
1124
        if (mode == AudioModeBluetooth) {
1125
            // there can be only one bluetooth
1126
            output.id = "bluetooth";
1127
            output.type = "bluetooth";
1128
            // we dont support names for now, so we set a default value
1129
            output.name = "bluetooth";
1130
        } else if (mode == AudioModeEarpiece || mode == AudioModeWiredHeadset) {
1131
            if (!defaultFound) {
1132
                defaultFound = true;
1133
                output.id = "default";
1134
                output.type = "default";
1135
                output.name = "default";
1136
            } else {
1137
                continue;
1138
            }
1139
        } else if (mode == AudioModeSpeaker) {
1140
            output.id = "speaker";
1141
            output.type = "speaker";
1142
            output.name = "speaker";
1143
        }
1144
        mAudioOutputs << output;
1145
    }
1146
    Q_EMIT audioOutputsChanged(mAudioOutputs);
101.1.1 by Ricardo Salveti de Araujo
Improve event handling from pulse, also exporting mode changes.
1147
}
1148
#endif
1149
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
1150
void oFonoConnection::updateAudioRoute()
1151
{
107.2.2 by Ricardo Salveti de Araujo
Better handling PA_DISABLED
1152
#ifdef USE_PULSEAUDIO
1153
    if (!mHasPulseAudio)
64.2.5 by Tiago Salem Herrmann
add env variable to disable pulseaudio
1154
        return;
107.2.2 by Ricardo Salveti de Araujo
Better handling PA_DISABLED
1155
#endif
64.2.5 by Tiago Salem Herrmann
add env variable to disable pulseaudio
1156
34.1.2 by Tiago Salem Herrmann
enable speaker phone mode on incoming calls.
1157
    int currentCalls = mOfonoVoiceCallManager->getCalls().size();
1158
    if (currentCalls != 0) {
1159
        if (currentCalls == 1) {
1160
            // if we have only one call, check if it's incoming and
1161
            // enable speaker mode so the ringtone is audible
1162
            OfonoVoiceCall *call = new OfonoVoiceCall(mOfonoVoiceCallManager->getCalls().first());
1163
            if (call) {
1164
                if (call->state() == "incoming") {
38.1.1 by David Henningsson
Add PulseAudio backend
1165
                    enable_ringtone();
34.1.2 by Tiago Salem Herrmann
enable speaker phone mode on incoming calls.
1166
                    call->deleteLater();
1167
                    return;
1168
                }
42.1.1 by Tiago Salem Herrmann
avoid changing to the wrong audio route on "disconnect"
1169
                if (call->state() == "disconnected") {
1170
                    enable_normal();
1171
                    call->deleteLater();
1172
                    return;
1173
                }
101.1.3 by Tiago Salem Herrmann
set earpiece when call status is "dialing"
1174
                // if only one call and dialing, default to earpiece
1175
                if (call->state() == "dialing") {
1176
                    enable_earpiece();
1177
                    call->deleteLater();
1178
                    return;
1179
                }
42.1.1 by Tiago Salem Herrmann
avoid changing to the wrong audio route on "disconnect"
1180
                if (call->state().isEmpty()) {
1181
                    call->deleteLater();
1182
                    return;
1183
                }
34.1.2 by Tiago Salem Herrmann
enable speaker phone mode on incoming calls.
1184
                call->deleteLater();
1185
            }
1186
        }
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
1187
    } else {
1188
        enable_normal();
105.2.6 by Andreas Pokorny
Use the triggers of VoiceCallManager to track that calls are available
1189
        Q_EMIT lastChannelClosed();
34.1.1 by Tiago Salem Herrmann
use audioflinger and implement speaker mode
1190
    }
1191
1192
}
1193
101.1.4 by Tiago Salem Herrmann
call enable_earpiece() on incoming calls, and only if this is the only call
1194
// this method is only called when call channels go from incoming to active.
1195
// please call this method only from oFonoCallChannel instances
1196
void oFonoConnection::updateAudioRouteToEarpiece()
1197
{
107.2.2 by Ricardo Salveti de Araujo
Better handling PA_DISABLED
1198
#ifdef USE_PULSEAUDIO
1199
    if (!mHasPulseAudio)
1200
        return;
1201
#endif
1202
101.1.4 by Tiago Salem Herrmann
call enable_earpiece() on incoming calls, and only if this is the only call
1203
    if (mOfonoVoiceCallManager->getCalls().size() == 1) {
1204
        enable_earpiece();
1205
    }
1206
}
154.1.1 by Tiago Salem Herrmann
Ensure uniqueName() is really unique. Using the object pointer is error-prone
1207
1208
QString oFonoConnection::uniqueName() const
1209
{
1210
    QString timestamp(QString::number(QDateTime::currentMSecsSinceEpoch()));
154.1.2 by Tiago Salem Herrmann
use toHex() to avoid garbage
1211
    QString md5(QCryptographicHash::hash(timestamp.toLatin1(), QCryptographicHash::Md5).toHex());
154.1.1 by Tiago Salem Herrmann
Ensure uniqueName() is really unique. Using the object pointer is error-prone
1212
    return QString(QLatin1String("connection_%1")).arg(md5);
1213
}