diff options
Diffstat (limited to 'rockworkd/platformintegration/sailfish/sailfishplatform.cpp')
| -rw-r--r-- | rockworkd/platformintegration/sailfish/sailfishplatform.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/rockworkd/platformintegration/sailfish/sailfishplatform.cpp b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp new file mode 100644 index 0000000..e31d65b --- /dev/null +++ b/rockworkd/platformintegration/sailfish/sailfishplatform.cpp @@ -0,0 +1,249 @@ +#include "sailfishplatform.h" + +#include "callchannelobserver.h" +#include "organizeradapter.h" +#include "syncmonitorclient.h" + +#include <QDBusConnection> +#include <QDBusConnectionInterface> +#include <QDebug> + +SailfishPlatform::SailfishPlatform(QObject *parent): + PlatformInterface(parent), + _pulseBus(NULL), + _maxVolume(0) +{ + // Notifications + QDBusConnection::sessionBus().registerObject("/org/freedesktop/Notifications", this, QDBusConnection::ExportAllSlots); + m_iface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); + m_iface->call("AddMatch", "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); + m_iface->call("AddMatch", "interface='org.freedesktop.Notifications',member='CloseNotification',type='method_call',eavesdrop='true'"); + + // Music + QDBusConnectionInterface *iface = QDBusConnection::sessionBus().interface(); + const QStringList &services = iface->registeredServiceNames(); + foreach (QString service, services) { + if (service.startsWith("org.mpris.MediaPlayer2.")) { + qDebug() << "have mpris service" << service; + m_mprisService = service; + fetchMusicMetadata(); + QDBusConnection::sessionBus().connect(m_mprisService, "/org/mpris/MediaPlayer2", "", "PropertiesChanged", this, SLOT(mediaPropertiesChanged(QString,QVariantMap,QStringList))); + break; + } + } + + QDBusMessage call = QDBusMessage::createMethodCall("org.PulseAudio1", "/org/pulseaudio/server_lookup1", "org.freedesktop.DBus.Properties", "Get" ); + call << "org.PulseAudio.ServerLookup1" << "Address"; + QDBusReply<QDBusVariant> lookupReply = QDBusConnection::sessionBus().call(call); + if (lookupReply.isValid()) { + // + qDebug() << "PulseAudio Bus address: " << lookupReply.value().variant().toString(); + _pulseBus = new QDBusConnection(QDBusConnection::connectToPeer(lookupReply.value().variant().toString(), "org.PulseAudio1")); + } + // Query max volume + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "StepCount"; + QDBusReply<QDBusVariant> volumeMaxReply = _pulseBus->call(call); + if (volumeMaxReply.isValid()) { + _maxVolume = volumeMaxReply.value().variant().toUInt(); + qDebug() << "Max volume: " << _maxVolume; + } + else { + qWarning() << "Could not read volume max, cannot adjust volume: " << volumeMaxReply.error().message(); + } + + // 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); + + // Organizer + m_organizerAdapter = new OrganizerAdapter(this); + m_organizerAdapter->refresh(); + connect(m_organizerAdapter, &OrganizerAdapter::itemsChanged, this, &SailfishPlatform::organizerItemsChanged); + m_syncMonitorClient = new SyncMonitorClient(this); + connect(m_syncMonitorClient, &SyncMonitorClient::stateChanged, [this]() { if (m_syncMonitorClient->state() == "idle") m_organizerAdapter->refresh();}); + m_syncTimer.start(1000 * 60 * 60); + connect(&m_syncTimer, &QTimer::timeout, [this]() { m_syncMonitorClient->sync({"calendar"});}); + m_syncMonitorClient->sync({"calendar"}); +} + +QDBusInterface *SailfishPlatform::interface() const +{ + return m_iface; +} + +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) +{ + // Lets directly suppress volume change notifications, network password entries and phone call snap decisions here + QStringList hiddenNotifications = {"indicator-sound", "indicator-network"}; + if (!hiddenNotifications.contains(app_name)) { + if (hints.contains("x-canonical-secondary-icon") && hints.value("x-canonical-secondary-icon").toString() == "incoming-call") { + qDebug() << "Have a phone call notification. Ignoring it..." << app_name << app_icon; + } else { + qDebug() << "Notification received" << app_name << replaces_id << app_icon << summary << body << actions << hints << expire_timeout; + Notification n(app_name); + if (app_name.contains("twitter")) { + n.setType(Notification::NotificationTypeTwitter); + n.setSourceName("Twitter"); + } else if (app_name.contains("dekko")) { + n.setType(Notification::NotificationTypeEmail); + n.setSourceName("EMail"); + } else if (app_name.toLower().contains("gmail")) { + n.setType(Notification::NotificationTypeGMail); + n.setSourceName("GMail"); + } else if (app_name.contains("facebook")) { + n.setType(Notification::NotificationTypeFacebook); + n.setSourceName("Facebook"); + } else if (app_name.toLower().contains("telegram") || app_name.toLower().contains("sailorgram")) { + n.setType(Notification::NotificationTypeTelegram); + n.setSourceName("Telegram"); + } else if (app_name.toLower().contains("hangish")) { + n.setType(Notification::NotificationTypeHangout); + n.setSourceName("Hangout"); + } else if (app_name.contains("indicator-datetime")) { + n.setType(Notification::NotificationTypeReminder); + n.setSourceName("reminders"); + } else { + n.setType(Notification::NotificationTypeGeneric); + } + n.setSender(summary); + n.setBody(body); + foreach (const QString &action, actions) { + if (action.contains(QRegExp("^[a-z]*://"))) { + n.setActToken(action); + break; + } + } + qDebug() << "have act token" << n.actToken(); + + emit notificationReceived(n); + } + } + // We never return something. We're just snooping in... + setDelayedReply(true); + return 0; +} + +void SailfishPlatform::sendMusicControlCommand(MusicControlButton controlButton) +{ + QString method; + switch (controlButton) { + case MusicControlPlayPause: + method = "PlayPause"; + break; + case MusicControlSkipBack: + method = "Previous"; + break; + case MusicControlSkipNext: + method = "Next"; + break; + default: + ; + } + + if (!method.isEmpty()) { + QDBusMessage call = QDBusMessage::createMethodCall(m_mprisService, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player", method); + QDBusError err = QDBusConnection::sessionBus().call(call); + + if (err.isValid()) { + qWarning() << "Error calling mpris method on" << m_mprisService << ":" << err.message(); + } + return; + } + + if (controlButton == MusicControlVolumeUp || controlButton == MusicControlVolumeDown) { + QDBusMessage call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Get"); + call << "com.Meego.MainVolume2" << "CurrentStep"; + + QDBusReply<QDBusVariant> volumeReply = _pulseBus->call(call); + if (volumeReply.isValid()) { + // Decide the new value for volume, taking limits into account + uint volume = volumeReply.value().variant().toUInt(); + uint newVolume; + qDebug() << "Current volume: " << volumeReply.value().variant().toUInt(); + if (controlButton == MusicControlVolumeUp && volume < _maxVolume-1 ) { + newVolume = volume + 1; + } + else if (controlButton == MusicControlVolumeDown && volume > 0) { + newVolume = volume - 1; + } + else { + qDebug() << "Volume already at limit"; + newVolume = volume; + } + + // If we have a new volume level, change it + if (newVolume != volume) { + qDebug() << "Setting volume: " << newVolume; + + call = QDBusMessage::createMethodCall("com.Meego.MainVolume2", "/com/meego/mainvolume2", + "org.freedesktop.DBus.Properties", "Set"); + call << "com.Meego.MainVolume2" << "CurrentStep" << QVariant::fromValue(QDBusVariant(newVolume)); + + QDBusError err = _pulseBus->call(call); + if (err.isValid()) { + qWarning() << err.message(); + } + } + } + } +} + +MusicMetaData SailfishPlatform::musicMetaData() const +{ + return m_musicMetaData; +} + +void SailfishPlatform::hangupCall(uint cookie) +{ + m_telepathyMonitor->hangupCall(cookie); +} + +QList<CalendarEvent> SailfishPlatform::organizerItems() const +{ + return m_organizerAdapter->items(); +} + +void SailfishPlatform::actionTriggered(const QString &actToken) +{ + Q_UNUSED(actToken); + //url_dispatch_send(actToken.toStdString().c_str(), [] (const char *, boolean, pointer) {}, nullptr); +} + +void SailfishPlatform::fetchMusicMetadata() +{ + if (!m_mprisService.isEmpty()) { + QDBusMessage call = QDBusMessage::createMethodCall(m_mprisService, "/org/mpris/MediaPlayer2", "org.freedesktop.DBus.Properties", "Get"); + call << "org.mpris.MediaPlayer2.Player" << "Metadata"; + QDBusPendingCall pcall = QDBusConnection::sessionBus().asyncCall(call); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, &SailfishPlatform::fetchMusicMetadataFinished); + } +} + +void SailfishPlatform::fetchMusicMetadataFinished(QDBusPendingCallWatcher *watcher) +{ + watcher->deleteLater(); + QDBusReply<QDBusVariant> reply = watcher->reply(); + if (reply.isValid()) { + QVariantMap curMetadata = qdbus_cast<QVariantMap>(reply.value().variant().value<QDBusArgument>()); + m_musicMetaData.artist = curMetadata.value("xesam:artist").toString(); + m_musicMetaData.album = curMetadata.value("xesam:album").toString(); + m_musicMetaData.title = curMetadata.value("xesam:title").toString(); + emit musicMetadataChanged(m_musicMetaData); + } else { + qWarning() << reply.error().message(); + } +} + +void SailfishPlatform::mediaPropertiesChanged(const QString &interface, const QVariantMap &changedProps, const QStringList &invalidatedProps) +{ + Q_UNUSED(interface) + Q_UNUSED(changedProps) + Q_UNUSED(invalidatedProps) + fetchMusicMetadata(); +} |
