From fcffc105918ccdb89638a71203f7688c4e75c664 Mon Sep 17 00:00:00 2001 From: "Friedrich W. H. Kossebau" Date: Thu, 29 Mar 2018 01:46:12 +0200 Subject: [PATCH] New plugin: Find this device Summary: Allows other devices to make this device discoverable via a kdeconnect.findmyphone.request command, if running. Currently supports playing a sound. Counterpart to FindMyPhone plugin Test Plan: Connect with other device running KDE Connect (with Plasmoid). Select a working play sound in the Find My Device plugin settings. On other device trigger Find My Phone button for this device in KDE Connect Plasmoid and notice this device playing the configured sound. Reviewers: #kde_connect, nicolasfella Reviewed By: #kde_connect, nicolasfella Subscribers: kdeconnect, sredman, mtijink, apol, nicolasfella Tags: #kde_connect Differential Revision: https://phabricator.kde.org/D11773 --- CMakeLists.txt | 6 + plugins/CMakeLists.txt | 3 + plugins/findthisdevice/CMakeLists.txt | 33 +++++ .../findthisdevice/findthisdevice_config.cpp | 123 ++++++++++++++++++ .../findthisdevice/findthisdevice_config.h | 50 +++++++ .../findthisdevice/findthisdevice_config.ui | 72 ++++++++++ .../findthisdevice/findthisdeviceplugin.cpp | 100 ++++++++++++++ plugins/findthisdevice/findthisdeviceplugin.h | 47 +++++++ .../kdeconnect_findthisdevice.json | 24 ++++ .../kdeconnect_findthisdevice_config.desktop | 10 ++ 10 files changed, 468 insertions(+) create mode 100644 plugins/findthisdevice/CMakeLists.txt create mode 100644 plugins/findthisdevice/findthisdevice_config.cpp create mode 100644 plugins/findthisdevice/findthisdevice_config.h create mode 100644 plugins/findthisdevice/findthisdevice_config.ui create mode 100644 plugins/findthisdevice/findthisdeviceplugin.cpp create mode 100644 plugins/findthisdevice/findthisdeviceplugin.h create mode 100644 plugins/findthisdevice/kdeconnect_findthisdevice.json create mode 100644 plugins/findthisdevice/kdeconnect_findthisdevice_config.desktop diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e4fed27c..7a9791fea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,12 @@ find_package(KF5 ${KF5_MIN_VERSION} OPTIONAL_COMPONENTS DocTools ) find_package(Qca-qt5 2.1.0 REQUIRED) +find_package(Phonon4Qt5 4.9.0 NO_MODULE) +set_package_properties(Phonon4Qt5 PROPERTIES + DESCRIPTION "Qt-based audio library" + TYPE OPTIONAL + PURPOSE "Required for Find My Device plugin" +) include_directories(${CMAKE_SOURCE_DIR}) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0c5bfdcb5..e2f1d8773 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -10,6 +10,9 @@ add_subdirectory(share) add_subdirectory(notifications) add_subdirectory(battery) add_subdirectory(findmyphone) +if(Phonon4Qt5_FOUND) + add_subdirectory(findthisdevice) +endif() add_subdirectory(remotekeyboard) add_subdirectory(mousepad) if(NOT WIN32) diff --git a/plugins/findthisdevice/CMakeLists.txt b/plugins/findthisdevice/CMakeLists.txt new file mode 100644 index 000000000..40cf3c650 --- /dev/null +++ b/plugins/findthisdevice/CMakeLists.txt @@ -0,0 +1,33 @@ +include_directories(${PHONON_INCLUDE_DIR}) + +set(kdeconnect_findthisdevice_SRCS + findthisdeviceplugin.cpp +) + +kdeconnect_add_plugin(kdeconnect_findthisdevice + JSON kdeconnect_findthisdevice.json + SOURCES ${kdeconnect_findthisdevice_SRCS}) + +target_link_libraries(kdeconnect_findthisdevice + kdeconnectcore + ${PHONON_LIBRARIES} + Qt5::Core + Qt5::DBus +) + + +set(kdeconnect_findthisdevice_config_SRCS findthisdevice_config.cpp) +ki18n_wrap_ui(kdeconnect_findthisdevice_config_SRCS findthisdevice_config.ui) + +add_library(kdeconnect_findthisdevice_config MODULE ${kdeconnect_findthisdevice_config_SRCS}) +target_link_libraries(kdeconnect_findthisdevice_config + kdeconnectpluginkcm + ${PHONON_LIBRARIES} + KF5::I18n + KF5::CoreAddons + KF5::ConfigWidgets + KF5::KIOWidgets # KUrlRequester +) + +install(TARGETS kdeconnect_findthisdevice_config DESTINATION ${KDE_INSTALL_PLUGINDIR}) +install(FILES kdeconnect_findthisdevice_config.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) diff --git a/plugins/findthisdevice/findthisdevice_config.cpp b/plugins/findthisdevice/findthisdevice_config.cpp new file mode 100644 index 000000000..7feba35ff --- /dev/null +++ b/plugins/findthisdevice/findthisdevice_config.cpp @@ -0,0 +1,123 @@ +/** + * Copyright 2018 Friedrich W. H. Kossebau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "findthisdevice_config.h" + +#include "ui_findthisdevice_config.h" +// Phonon +#include +// KF +#include +#include +// Qt +#include + + +K_PLUGIN_FACTORY(FindThisDeviceConfigFactory, registerPlugin();) + + +namespace { +namespace Strings { +inline QString defaultSound() { return QStringLiteral("Oxygen-Im-Phone-Ring.ogg"); } +} +} + +FindThisDeviceConfig::FindThisDeviceConfig(QWidget* parent, const QVariantList& args) + : KdeConnectPluginKcm(parent, args, QStringLiteral("kdeconnect_findthisdevice_config")) + , m_ui(new Ui::FindThisDeviceConfigUi()) +{ + m_ui->setupUi(this); + + const QStringList soundDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, + QStringLiteral("sounds"), + QStandardPaths::LocateDirectory); + if (!soundDirs.isEmpty()) { + m_ui->soundFileRequester->setStartDir(QUrl::fromLocalFile(soundDirs.last())); + } + + connect(m_ui->playSoundButton, &QToolButton::clicked, + this, &FindThisDeviceConfig::playSound); + connect(m_ui->soundFileRequester, &KUrlRequester::textChanged, + this, static_cast(&KdeConnectPluginKcm::changed)); +} + +FindThisDeviceConfig::~FindThisDeviceConfig() +{ + delete m_ui; +} + + +void FindThisDeviceConfig::defaults() +{ + KCModule::defaults(); + + m_ui->soundFileRequester->setText(Strings::defaultSound()); + + Q_EMIT changed(true); +} + +void FindThisDeviceConfig::load() +{ + KCModule::load(); + + const QString ringTone = config()->get(QStringLiteral("ringtone"), Strings::defaultSound()); + m_ui->soundFileRequester->setText(ringTone); + + Q_EMIT changed(false); +} + +void FindThisDeviceConfig::save() +{ + config()->set(QStringLiteral("ringtone"), m_ui->soundFileRequester->text()); + + KCModule::save(); + + Q_EMIT changed(false); +} + +void FindThisDeviceConfig::playSound() +{ + const QString soundFilename = m_ui->soundFileRequester->text(); + + QUrl soundURL; + const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &dataLocation : dataLocations) { + soundURL = QUrl::fromUserInput(soundFilename, + dataLocation + QStringLiteral("/sounds"), + QUrl::AssumeLocalFile); + if (soundURL.isLocalFile()) { + if (QFile::exists(soundURL.toLocalFile())) { + break; + } + } else { + if (soundURL.isValid()) { + break; + } + } + soundURL.clear(); + } + + Phonon::MediaObject *media = Phonon::createPlayer(Phonon::NotificationCategory, soundURL); + media->play(); + connect(media, SIGNAL(finished()), media, SLOT(deleteLater())); +} + + +#include "findthisdevice_config.moc" diff --git a/plugins/findthisdevice/findthisdevice_config.h b/plugins/findthisdevice/findthisdevice_config.h new file mode 100644 index 000000000..6354ce4db --- /dev/null +++ b/plugins/findthisdevice/findthisdevice_config.h @@ -0,0 +1,50 @@ +/** + * Copyright 2018 Friedrich W. H. Kossebau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FINDTHISDEVICE_CONFIG_H +#define FINDTHISDEVICE_CONFIG_H + +#include + +namespace Ui { +class FindThisDeviceConfigUi; +} + +class FindThisDeviceConfig + : public KdeConnectPluginKcm +{ + Q_OBJECT +public: + FindThisDeviceConfig(QWidget* parent, const QVariantList&); + ~FindThisDeviceConfig() override; + +public Q_SLOTS: + void save() override; + void load() override; + void defaults() override; + +private Q_SLOTS: + void playSound(); + +private: + Ui::FindThisDeviceConfigUi* m_ui; +}; + +#endif diff --git a/plugins/findthisdevice/findthisdevice_config.ui b/plugins/findthisdevice/findthisdevice_config.ui new file mode 100644 index 000000000..ef09e9336 --- /dev/null +++ b/plugins/findthisdevice/findthisdevice_config.ui @@ -0,0 +1,72 @@ + + + FindThisDeviceConfigUi + + + + 0 + 0 + 569 + 140 + + + + + + + Discovery Utilities + + + + + + + + Sound to play: + + + + + + + + + + + + + + Select the sound to play + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + KUrlRequester + QWidget +
kurlrequester.h
+
+
+ + +
diff --git a/plugins/findthisdevice/findthisdeviceplugin.cpp b/plugins/findthisdevice/findthisdeviceplugin.cpp new file mode 100644 index 000000000..48bcf4482 --- /dev/null +++ b/plugins/findthisdevice/findthisdeviceplugin.cpp @@ -0,0 +1,100 @@ +/** + * Copyright 2018 Friedrich W. H. Kossebau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "findthisdeviceplugin.h" + +// Phonon +#include +// KF +#include +// Qt +#include +#include +#include +#include + + +K_PLUGIN_FACTORY_WITH_JSON(KdeConnectPluginFactory, "kdeconnect_findthisdevice.json", + registerPlugin();) + +Q_LOGGING_CATEGORY(KDECONNECT_PLUGIN_FINDTHISDEVICE, "kdeconnect.plugin.findthisdevice") + +namespace { +namespace Strings { +inline QString defaultSound() { return QStringLiteral("Oxygen-Im-Phone-Ring.ogg"); } +} +} + +FindThisDevicePlugin::FindThisDevicePlugin(QObject* parent, const QVariantList& args) + : KdeConnectPlugin(parent, args) +{ +} + +FindThisDevicePlugin::~FindThisDevicePlugin() = default; + +void FindThisDevicePlugin::connected() +{ +} + +bool FindThisDevicePlugin::receivePacket(const NetworkPacket& np) +{ + Q_UNUSED(np); + + const QString soundFilename = config()->get(QStringLiteral("ringtone"), Strings::defaultSound()); + + QUrl soundURL; + const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &dataLocation : dataLocations) { + soundURL = QUrl::fromUserInput(soundFilename, + dataLocation + QStringLiteral("/sounds"), + QUrl::AssumeLocalFile); + if (soundURL.isLocalFile()) { + if (QFile::exists(soundURL.toLocalFile())) { + break; + } + } else { + if (soundURL.isValid()) { + break; + } + } + soundURL.clear(); + } + if (soundURL.isEmpty()) { + qCWarning(KDECONNECT_PLUGIN_FINDTHISDEVICE) << "Not playing sounds, could not find ring tone" << soundFilename; + return true; + } + + Phonon::MediaObject *media = Phonon::createPlayer(Phonon::NotificationCategory, soundURL); // or CommunicationCategory? + media->play(); + connect(media, &Phonon::MediaObject::finished, media, &QObject::deleteLater); + + // TODO: by-pass volume settings in case it is muted + // TODO: ensure to use built-in loudspeakers + + return true; +} + +QString FindThisDevicePlugin::dbusPath() const +{ + return "/modules/kdeconnect/devices/" + device()->id() + "/findthisdevice"; +} + +#include "findthisdeviceplugin.moc" + diff --git a/plugins/findthisdevice/findthisdeviceplugin.h b/plugins/findthisdevice/findthisdeviceplugin.h new file mode 100644 index 000000000..3df265909 --- /dev/null +++ b/plugins/findthisdevice/findthisdeviceplugin.h @@ -0,0 +1,47 @@ +/** + * Copyright 2018 Friedrich W. H. Kossebau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FINDTHISDEVICEPLUGIN_H +#define FINDTHISDEVICEPLUGIN_H + +#include +// Qt +#include + +#define PACKET_TYPE_FINDMYPHONE_REQUEST QStringLiteral("kdeconnect.findmyphone.request") + +Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_PLUGIN_FINDTHISDEVICE) + +class FindThisDevicePlugin + : public KdeConnectPlugin +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.findthisdevice") + +public: + explicit FindThisDevicePlugin(QObject* parent, const QVariantList& args); + ~FindThisDevicePlugin() override; + + QString dbusPath() const override; + void connected() override; + bool receivePacket(const NetworkPacket& np) override; +}; + +#endif diff --git a/plugins/findthisdevice/kdeconnect_findthisdevice.json b/plugins/findthisdevice/kdeconnect_findthisdevice.json new file mode 100644 index 000000000..490c87349 --- /dev/null +++ b/plugins/findthisdevice/kdeconnect_findthisdevice.json @@ -0,0 +1,24 @@ +{ + "KPlugin": { + "Authors": [ + { + "Email": "kossebau@kde.org", + "Name": "Friedrich W. H. Kossebau" + } + ], + "Description": "Find this device by making it play an alarm sound", + "EnabledByDefault": true, + "Icon": "edit-find", + "Id": "kdeconnect_findthisdevice", + "License": "GPL", + "Name": "Find this device", + "ServiceTypes": [ + "KdeConnect/Plugin" + ], + "Version": "0.1", + "Website": "https://kde.org" + }, + "X-KdeConnect-SupportedPacketType": [ + "kdeconnect.findmyphone.request" + ] +} diff --git a/plugins/findthisdevice/kdeconnect_findthisdevice_config.desktop b/plugins/findthisdevice/kdeconnect_findthisdevice_config.desktop new file mode 100644 index 000000000..92b0c1339 --- /dev/null +++ b/plugins/findthisdevice/kdeconnect_findthisdevice_config.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kdeconnect_findthisdevice_config +X-KDE-ParentComponents=kdeconnect_findthisdevice + +Name=Find This Device plugin settings + +Categories=Qt;KDE;X-KDE-settings-kdeconnect;