diff options
| author | Andrew Branson <andrew.branson@cern.ch> | 2016-02-18 16:57:06 +0100 |
|---|---|---|
| committer | Andrew Branson <andrew.branson@cern.ch> | 2016-02-18 16:57:06 +0100 |
| commit | bd34e5b5ab78e15ee1433a7fbd1dfe2b672fef7f (patch) | |
| tree | ea6d65880e7fb822d198db029fb90b1dab1b1ad8 /rockworkd/platformintegration/sailfish | |
| parent | b9e47c9b12a54bef3cd5e21b93c85210e6abf227 (diff) | |
Ifdefed the WebSocket stuff that doesn't exist on Sailfish
Voice calls nearly working, except for a segfault on callEnded, which
might be a reentrant thing.
Diffstat (limited to 'rockworkd/platformintegration/sailfish')
7 files changed, 116 insertions, 258 deletions
diff --git a/rockworkd/platformintegration/sailfish/callchannelobserver.cpp b/rockworkd/platformintegration/sailfish/callchannelobserver.cpp deleted file mode 100644 index a9f41f3..0000000 --- a/rockworkd/platformintegration/sailfish/callchannelobserver.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#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, SLOT(accountManagerSetup())); - QMap<QString, QString> parameters; - parameters.insert(QString::fromLatin1("mergePresenceChanges"), QString::fromLatin1("false")); - m_contactManager = new QContactManager("", parameters, this); -} - -void TelepathyMonitor::hangupCall(uint cookie) -{ - if (m_currentCalls.contains(cookie)) { - m_currentCalls.value(cookie)->hangup(); - } -} - -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, SLOT(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) -{ - // Haven't figured how to send outgoing calls to pebble yet... discard it - if (callChannel->initiatorContact()->id().isEmpty()) { - qWarning() << "ignoring phone call. looks like it's an outgoing one"; - return; - } - - 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(); - qDebug() << "call started" << number; - - // 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); -} diff --git a/rockworkd/platformintegration/sailfish/callchannelobserver.h b/rockworkd/platformintegration/sailfish/callchannelobserver.h deleted file mode 100644 index ba3415d..0000000 --- a/rockworkd/platformintegration/sailfish/callchannelobserver.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef CALLCHANNELOBSERVER_H -#define CALLCHANNELOBSERVER_H - -#include <TelepathyQt/AccountManager> -#include <TelepathyQt/SimpleCallObserver> -#include <TelepathyQt/PendingOperation> -#include <TelepathyQt/PendingReady> -#include <TelepathyQt/PendingAccount> -#include <TelepathyQt/CallChannel> - -#include <QContactManager> - -QTCONTACTS_USE_NAMESPACE - -class TelepathyCallMonitor : public QObject -{ - Q_OBJECT -public: - TelepathyCallMonitor(const Tp::AccountPtr& account): - mAccount(account), - mCallObserver(Tp::SimpleCallObserver::create(mAccount)) { - connect(mCallObserver.data(), SIGNAL(callStarted(Tp::CallChannelPtr)), SIGNAL(callStarted(Tp::CallChannelPtr))); -// connect(mCallObserver.data(), SIGNAL(callEnded(Tp::CallChannelPtr,QString,QString)), SIGNAL(callEnded())); -// connect(mCallObserver.data(), SIGNAL(streamedMediaCallStarted(Tp::StreamedMediaChannelPtr)), SIGNAL(offHook())); -// connect(mCallObserver.data(), SIGNAL(streamedMediaCallEnded(Tp::StreamedMediaChannelPtr,QString,QString)), SIGNAL(onHook())); - } - -signals: - void callStarted(Tp::CallChannelPtr callChannel); - void callEnded(); - -private: - Tp::AccountPtr mAccount; - Tp::SimpleCallObserverPtr mCallObserver; -}; - -class TelepathyMonitor: public QObject -{ - Q_OBJECT -public: - TelepathyMonitor(QObject *parent = 0); - - void hangupCall(uint cookie); - -private slots: - void accountManagerSetup(); - void accountManagerReady(Tp::PendingOperation* operation); - - void newAccount(const Tp::AccountPtr& account); - void accountReady(Tp::PendingOperation* operation); - - void onCallStarted(Tp::CallChannelPtr callChannel); - void callStateChanged(Tp::CallState state); - -signals: - void incomingCall(uint cookie, const QString &number, const QString &name); - void callStarted(uint cookie); - void callEnded(uint cookie, bool missed); - -private: - void checkAndAddAccount(const Tp::AccountPtr& account); - -private: - Tp::AccountManagerPtr m_accountManager; - QList<TelepathyCallMonitor*> m_callMonitors; - QContactManager *m_contactManager; - - QHash<uint, Tp::CallChannel*> m_currentCalls; - QHash<uint, Tp::CallState> m_currentCallStates; - - uint m_cookie = 0; -}; - -#endif // CALLCHANNELOBSERVER_H diff --git a/rockworkd/platformintegration/sailfish/organizeradapter.cpp b/rockworkd/platformintegration/sailfish/organizeradapter.cpp index 416aad2..3e3c864 100644 --- a/rockworkd/platformintegration/sailfish/organizeradapter.cpp +++ b/rockworkd/platformintegration/sailfish/organizeradapter.cpp @@ -24,6 +24,7 @@ OrganizerAdapter::OrganizerAdapter(QObject *parent) : QObject(parent) m_manager->setParent(this); connect(m_manager, &QOrganizerManager::dataChanged, this, &OrganizerAdapter::refresh); + // This is the snippet from Fahrplan that enumerates the calendars, but here it doesn't seem to have permission to access the db mKCal::ExtendedCalendar::Ptr calendar = mKCal::ExtendedCalendar::Ptr ( new mKCal::ExtendedCalendar( QLatin1String( "UTC" ) ) ); mKCal::ExtendedStorage::Ptr storage = mKCal::ExtendedCalendar::defaultStorage( calendar ); if (storage->open()) { diff --git a/rockworkd/platformintegration/sailfish/sailfishplatform.cpp b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp index 09e1426..bcd834f 100644 --- a/rockworkd/platformintegration/sailfish/sailfishplatform.cpp +++ b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp @@ -1,12 +1,14 @@ #include "sailfishplatform.h" -#include "callchannelobserver.h" +#include "voicecallhandler.h" +#include "voicecallmanager.h" #include "organizeradapter.h" #include "syncmonitorclient.h" #include <QDBusConnection> #include <QDBusConnectionInterface> #include <QDebug> +#include <QSettings> SailfishPlatform::SailfishPlatform(QObject *parent): PlatformInterface(parent), @@ -54,10 +56,10 @@ SailfishPlatform::SailfishPlatform(QObject *parent): } // Calls - m_telepathyMonitor = new TelepathyMonitor(this); - connect(m_telepathyMonitor, &TelepathyMonitor::incomingCall, this, &SailfishPlatform::incomingCall); - connect(m_telepathyMonitor, &TelepathyMonitor::callStarted, this, &SailfishPlatform::callStarted); - connect(m_telepathyMonitor, &TelepathyMonitor::callEnded, this, &SailfishPlatform::callEnded); + m_voiceCallManager = new VoiceCallManager(this); + + connect(m_voiceCallManager, SIGNAL(activeVoiceCallChanged()), SLOT(onActiveVoiceCallChanged())); + connect(m_voiceCallManager, SIGNAL(error(const QString &)), SLOT(onVoiceError(const QString &))); // Organizer m_organizerAdapter = new OrganizerAdapter(this); @@ -75,6 +77,51 @@ QDBusInterface *SailfishPlatform::interface() const return m_iface; } +void SailfishPlatform::onActiveVoiceCallChanged() +{ + + VoiceCallHandler* handler = m_voiceCallManager->activeVoiceCall(); + if (handler) { + connect(handler, SIGNAL(statusChanged()), SLOT(onActiveVoiceCallStatusChanged())); + connect(handler, SIGNAL(destroyed()), SLOT(onActiveVoiceCallStatusChanged())); + if (handler->status()) onActiveVoiceCallStatusChanged(); + } +} + +void SailfishPlatform::onActiveVoiceCallStatusChanged() +{ + VoiceCallHandler* handler = m_voiceCallManager->activeVoiceCall(); + + if (!handler) { + return; + } + + uint handlerId = qHash(handler->handlerId()); + switch ((VoiceCallHandler::VoiceCallStatus)handler->status()) { + case VoiceCallHandler::STATUS_ALERTING: + case VoiceCallHandler::STATUS_DIALING: + qDebug() << "Tell outgoing:" << handler->lineId(); + //emit outgoingCall(handlerId, handler->lineId(), m_voiceCallManager->findPersonByNumber(handler->lineId())); + break; + case VoiceCallHandler::STATUS_INCOMING: + case VoiceCallHandler::STATUS_WAITING: + qDebug() << "Tell incoming:" << handler->lineId(); + emit incomingCall(handlerId, handler->lineId(), m_voiceCallManager->findPersonByNumber(handler->lineId())); + break; + case VoiceCallHandler::STATUS_NULL: + case VoiceCallHandler::STATUS_DISCONNECTED: + qDebug() << "Endphone"; + emit callEnded(handlerId, false); + break; + case VoiceCallHandler::STATUS_ACTIVE: + qDebug() << "Startphone"; + emit callStarted(handlerId); + break; + case VoiceCallHandler::STATUS_HELD: + break; + } +} + uint SailfishPlatform::Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout) { qDebug() << "Notification received" << app_name << replaces_id << app_icon << summary << body << actions << hints << expire_timeout; @@ -236,7 +283,7 @@ MusicMetaData SailfishPlatform::musicMetaData() const void SailfishPlatform::hangupCall(uint cookie) { - m_telepathyMonitor->hangupCall(cookie); + m_voiceCallManager->hangUp(cookie); } QList<CalendarEvent> SailfishPlatform::organizerItems() const diff --git a/rockworkd/platformintegration/sailfish/sailfishplatform.h b/rockworkd/platformintegration/sailfish/sailfishplatform.h index e18b986..82ce383 100644 --- a/rockworkd/platformintegration/sailfish/sailfishplatform.h +++ b/rockworkd/platformintegration/sailfish/sailfishplatform.h @@ -3,12 +3,14 @@ #include "libpebble/platforminterface.h" #include "libpebble/enums.h" +#include "voicecallmanager.h" +#include "voicecallhandler.h" #include <QDBusInterface> -#include <TelepathyQt/AbstractClientObserver> +#include <QDBusContext> class QDBusPendingCallWatcher; -class TelepathyMonitor; +class VoiceCallManager; class OrganizerAdapter; class SyncMonitorClient; @@ -29,17 +31,17 @@ public: QHash<QString, QString> getCategoryParams(QString category); QList<CalendarEvent> organizerItems() const override; - void actionTriggered(const QString &actToken) override; public slots: uint Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout); - private slots: void fetchMusicMetadata(); void fetchMusicMetadataFinished(QDBusPendingCallWatcher *watcher); void mediaPropertiesChanged(const QString &interface, const QVariantMap &changedProps, const QStringList &invalidatedProps); + void onActiveVoiceCallChanged(); + void onActiveVoiceCallStatusChanged(); private: QDBusInterface *m_iface; @@ -49,7 +51,7 @@ private: QDBusConnection *_pulseBus; uint _maxVolume; - TelepathyMonitor *m_telepathyMonitor; + VoiceCallManager *m_voiceCallManager; OrganizerAdapter *m_organizerAdapter; SyncMonitorClient *m_syncMonitorClient; QTimer m_syncTimer; diff --git a/rockworkd/platformintegration/sailfish/voicecallmanager.cpp b/rockworkd/platformintegration/sailfish/voicecallmanager.cpp index afb3629..eda4fe3 100644 --- a/rockworkd/platformintegration/sailfish/voicecallmanager.cpp +++ b/rockworkd/platformintegration/sailfish/voicecallmanager.cpp @@ -4,6 +4,10 @@ #include <QTimer> #include <QDBusInterface> #include <QDBusPendingReply> +#include <QtContacts/QContactManager> +#include <QtContacts/QContactDetailFilter> +#include <QtContacts/QContactPhoneNumber> + class VoiceCallManagerPrivate { @@ -29,8 +33,8 @@ public: bool connected; }; -VoiceCallManager::VoiceCallManager(Settings *settings, QObject *parent) - : QObject(parent), l(metaObject()->className()), d_ptr(new VoiceCallManagerPrivate(this)), settings(settings) +VoiceCallManager::VoiceCallManager(QObject *parent) + : QObject(parent), l(metaObject()->className()), d_ptr(new VoiceCallManagerPrivate(this)) { this->initialize(); } @@ -46,6 +50,13 @@ void VoiceCallManager::initialize(bool notifyError) Q_D(VoiceCallManager); bool success = false; + QMap<QString, QString> parameters; + parameters.insert(QString::fromLatin1("mergePresenceChanges"), QString::fromLatin1("false")); + contacts = new QContactManager("", parameters, this); + + numberFilter.setDetailType(QContactDetail::TypePhoneNumber, QContactPhoneNumber::FieldNumber); + numberFilter.setMatchFlags(QContactFilter::MatchPhoneNumber); + delete d->interface; d->interface = new QDBusInterface("org.nemomobile.voicecall", "/", @@ -109,6 +120,18 @@ QString VoiceCallManager::defaultProviderId() const return provider.id; } +QString VoiceCallManager::findPersonByNumber(QString number) +{ + QString person; + numberFilter.setValue(number); + + const QList<QContact> &found = contacts->contacts(numberFilter); + if (found.size() > 0) { + person = found[0].detail(QContactDetail::TypeDisplayLabel).value(0).toString(); + } + return person; +} + VoiceCallHandler* VoiceCallManager::activeVoiceCall() const { Q_D(const VoiceCallManager); @@ -139,6 +162,11 @@ bool VoiceCallManager::isSpeakerMuted() const return d->interface->property("isSpeakerMuted").toBool(); } +void VoiceCallManager::onVoiceError(const QString &message) +{ + qCritical() << "Error:" << message; +} + void VoiceCallManager::dial(const QString &provider, const QString &msisdn) { Q_D(VoiceCallManager); @@ -148,6 +176,16 @@ void VoiceCallManager::dial(const QString &provider, const QString &msisdn) QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onPendingCallFinished(QDBusPendingCallWatcher*))); } +void VoiceCallManager::hangUp(uint cookie) { + foreach (VoiceCallHandler* handler, voiceCalls()) { + uint handlerId = qHash(handler->handlerId()); + if (cookie == handlerId) { + handler->hangup(); + return; + } + } +} + void VoiceCallManager::hangupAll() { foreach (VoiceCallHandler* handler, voiceCalls()) { @@ -196,6 +234,7 @@ bool VoiceCallManager::setMuteSpeaker(bool on) void VoiceCallManager::onVoiceCallsChanged() { + qDebug() << "VoiceCallsChanged"; Q_D(VoiceCallManager); QStringList nIds = d->interface->property("voiceCalls").toStringList(); QStringList oIds; @@ -226,8 +265,10 @@ void VoiceCallManager::onVoiceCallsChanged() { for (int i = 0; i < d->voicecalls.count(); ++i) { VoiceCallHandler *handler = d->voicecalls.at(i); + if (!handler) continue; if(handler->handlerId() == removeId) { + qDebug() << "removing " << handler->handlerId(); handler->disconnect(this); d->voicecalls.removeAt(i); handler->deleteLater(); @@ -239,6 +280,7 @@ void VoiceCallManager::onVoiceCallsChanged() // Add handlers that need to be added. foreach(QString addId, added) { + qDebug() << "adding " << addId; VoiceCallHandler *handler = new VoiceCallHandler(addId, this); d->voicecalls.append(handler); } @@ -263,6 +305,7 @@ void VoiceCallManager::onProvidersChanged() void VoiceCallManager::onActiveVoiceCallChanged() { + qDebug() << "ActiveVoiceCallChanged"; Q_D(VoiceCallManager); QString voiceCallId = d->interface->property("activeVoiceCall").toString(); diff --git a/rockworkd/platformintegration/sailfish/voicecallmanager.h b/rockworkd/platformintegration/sailfish/voicecallmanager.h index ec51230..92056c8 100644 --- a/rockworkd/platformintegration/sailfish/voicecallmanager.h +++ b/rockworkd/platformintegration/sailfish/voicecallmanager.h @@ -2,12 +2,15 @@ #define VOICECALLMANAGER_H #include "voicecallhandler.h" -#include "settings.h" #include <QObject> #include <QDBusInterface> #include <QDBusPendingCallWatcher> #include <QLoggingCategory> +#include <QtContacts/QContactManager> +#include <QtContacts/QContactDetailFilter> + +using namespace QtContacts; class VoiceCallProviderData { @@ -45,7 +48,7 @@ class VoiceCallManager : public QObject Q_PROPERTY(bool isSpeakerMuted READ isSpeakerMuted WRITE setMuteSpeaker NOTIFY speakerMutedChanged) public: - explicit VoiceCallManager(Settings *settings, QObject *parent = 0); + explicit VoiceCallManager(QObject *parent = 0); ~VoiceCallManager(); QDBusInterface* interface() const; @@ -56,6 +59,8 @@ public: QString defaultProviderId() const; VoiceCallHandler* activeVoiceCall() const; + QString findPersonByNumber(QString number); + void hangUp(uint cookie); QString audioMode() const; bool isAudioRouted() const; @@ -95,14 +100,14 @@ protected Q_SLOTS: void onProvidersChanged(); void onVoiceCallsChanged(); void onActiveVoiceCallChanged(); - + void onVoiceError(const QString &message); void onPendingCallFinished(QDBusPendingCallWatcher *watcher); void onPendingSilenceFinished(QDBusPendingCallWatcher *watcher); private: class VoiceCallManagerPrivate *d_ptr; - - Settings *settings; + QContactManager *contacts; + QContactDetailFilter numberFilter; Q_DISABLE_COPY(VoiceCallManager) Q_DECLARE_PRIVATE(VoiceCallManager) |
