diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index a2118e7..373eac6 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,45 +1,47 @@ add_subdirectory(fakebluez) include(ECMMarkAsTest) set(bluezqt_autotests_SRCS autotests.cpp ) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.Properties.xml dbusproperties_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Adapter1.xml bluezadapter1_tst) +qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Battery1.xml bluezbattery1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Device1.xml bluezdevice1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaPlayer1.xml bluezmediaplayer1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaTransport1.xml bluezmediatransport1_tst) qt5_add_dbus_interface(bluezqt_autotests_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Input1.xml bluezinput1_tst) macro(bluezqt_tests) foreach(_testname ${ARGN}) add_executable(${_testname} ${_testname}.cpp ${bluezqt_autotests_SRCS}) target_link_libraries(${_testname} Qt5::DBus Qt5::Test KF5BluezQt) add_test(NAME bluezqt-${_testname} COMMAND ${_testname}) ecm_mark_as_test(${_testname}) set_tests_properties(bluezqt-${_testname} PROPERTIES RUN_SERIAL TRUE) endforeach(_testname) endmacro() bluezqt_tests( managertest agentmanagertest obexmanagertest adaptertest + batterytest devicetest inputtest mediaplayertest mediatransporttest jobstest mediatest leadvertisingmanagertest gattmanagertest ) if(Qt5Qml_FOUND AND Qt5QuickTest_FOUND) bluezqt_tests(qmltests) target_link_libraries(qmltests Qt5::Qml Qt5::QuickTest) add_definitions(-DBLUEZQT_QML_IMPORT_PATH="${CMAKE_CURRENT_BINARY_DIR}/../src/imports") endif() diff --git a/autotests/autotests.cpp b/autotests/autotests.cpp index ac986cc..489dd68 100644 --- a/autotests/autotests.cpp +++ b/autotests/autotests.cpp @@ -1,204 +1,206 @@ /* * Copyright (C) 2014-2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "autotests.h" #include "device.h" #include "adapter.h" +#include "battery.h" #include "mediaplayer.h" #include "mediaplayertrack.h" #include "mediatransport.h" #include "bluezqt_dbustypes.h" #include #include #include #include #include #include QProcess *FakeBluez::s_process = nullptr; class StartJob : public QObject { Q_OBJECT public: explicit StartJob(); void exec(); bool foundFakeBluez() const { return !m_fakebluezPath.isEmpty(); } private Q_SLOTS: void processError(QProcess::ProcessError error); void processFinished(int code, QProcess::ExitStatus status); private: QString m_fakebluezPath; QEventLoop m_eventLoop; }; StartJob::StartJob() : QObject(nullptr) , m_fakebluezPath(QCoreApplication::applicationDirPath() + QStringLiteral("/fakebluez")) { } void StartJob::exec() { QDBusServiceWatcher watcher(QStringLiteral("org.kde.bluezqt.test"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration); connect(&watcher, &QDBusServiceWatcher::serviceRegistered, &m_eventLoop, &QEventLoop::quit); connect(FakeBluez::s_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); connect(FakeBluez::s_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus))); FakeBluez::s_process->start(m_fakebluezPath, QStringList()); m_eventLoop.exec(); } void StartJob::processError(QProcess::ProcessError error) { QString errorString; switch (error) { case QProcess::FailedToStart: errorString = QStringLiteral("Failed to Start"); break; case QProcess::Crashed: errorString = QStringLiteral("Crashed"); break; case QProcess::Timedout: errorString = QStringLiteral("Timedout"); break; default: errorString = QStringLiteral("Unknown"); } qWarning() << "Fakebluez binary:" << m_fakebluezPath; qWarning() << "Process error:" << error << errorString; qWarning() << "Error output:" << FakeBluez::s_process->readAllStandardError(); m_eventLoop.quit(); } void StartJob::processFinished(int code, QProcess::ExitStatus status) { QString statusString = status == QProcess::NormalExit ? QStringLiteral("Normal Exit") : QStringLiteral("Crash Exit"); qWarning() << "Fakebluez binary:" << m_fakebluezPath; qWarning() << "Process finished:" << code << statusString; qWarning() << "Error output:" << FakeBluez::s_process->readAllStandardError(); m_eventLoop.quit(); } void FakeBluez::start() { if (isRunning()) { return; } if (!s_process) { s_process = new QProcess(); } StartJob job; QVERIFY(job.foundFakeBluez()); job.exec(); } void FakeBluez::stop() { if (s_process && s_process->state() == QProcess::Running) { s_process->terminate(); s_process->waitForFinished(); } } bool FakeBluez::isRunning() { return s_process && s_process->state() == QProcess::Running; } void FakeBluez::runTest(const QString &testName) { if (!isRunning()) { return; } QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.bluezqt.test"), QStringLiteral("/"), QStringLiteral("org.kde.bluezqt.fakebluez.Test"), QStringLiteral("runTest")); call << testName; QDBusConnection::sessionBus().call(call); } void FakeBluez::runAction(const QString &object, const QString &actionName, const QVariantMap &properties) { if (!isRunning()) { return; } QDBusMessage call = QDBusMessage::createMethodCall(QStringLiteral("org.kde.bluezqt.test"), QStringLiteral("/"), QStringLiteral("org.kde.bluezqt.fakebluez.Test"), QStringLiteral("runAction")); call << object; call << actionName; call << properties; QDBusConnection::sessionBus().call(call); } void Autotests::registerMetatypes() { qRegisterMetaType("DevicePtr"); qRegisterMetaType("AdapterPtr"); + qRegisterMetaType("BatteryPtr"); qRegisterMetaType("MediaPlayerPtr"); qRegisterMetaType("MediaTransportPtr"); } void Autotests::verifyPropertiesChangedSignal(const QSignalSpy &spy, const QString &propertyName, const QVariant &propertyValue) { int changes = 0; for (int i = 0; i < spy.count(); ++i) { QList arguments = spy.at(i); QVariantMap properties = arguments.at(1).toMap(); QVariantMap::const_iterator it; for (it = properties.constBegin(); it != properties.constEnd(); ++it) { const QVariant &changedValue = it.value(); const QString &property = it.key(); if (property == propertyName && changedValue == propertyValue) { changes++; } } } QCOMPARE(changes, 1); } #include "autotests.moc" diff --git a/autotests/batterytest.cpp b/autotests/batterytest.cpp new file mode 100644 index 0000000..ac0af11 --- /dev/null +++ b/autotests/batterytest.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "batterytest.h" +#include "autotests.h" +#include "pendingcall.h" +#include "initmanagerjob.h" + +#include + +namespace BluezQt +{ +extern void bluezqt_initFakeBluezTestRun(); +} + +using namespace BluezQt; + +BatteryTest::BatteryTest() + : m_manager(nullptr) +{ + Autotests::registerMetatypes(); +} + +void BatteryTest::initTestCase() +{ + QDBusConnection connection = QDBusConnection::sessionBus(); + QString service = QStringLiteral("org.kde.bluezqt.fakebluez"); + + bluezqt_initFakeBluezTestRun(); + + FakeBluez::start(); + FakeBluez::runTest(QStringLiteral("bluez-standard")); + + // Create adapter + QString adapter = QStringLiteral("/org/bluez/hci0"); + QVariantMap adapterProps; + adapterProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(adapter)); + adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E"); + adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter"); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); + + // Create devices + QVariantMap deviceProps; + QVariantMap batteryProps; + + QString device1 = adapter + QLatin1String("/dev_40_79_6A_0C_39_75"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device1)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("40:79:6A:0C:39:75"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(42); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device2 = adapter + QLatin1String("/dev_50_79_6A_0C_39_75"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device2)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("50:79:6A:0C:39:75"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice2"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(0); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device3 = adapter + QLatin1String("/dev_60_79_6B_0C_39_55"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device3)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("60:79:6B:0C:39:55"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice3"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(99); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + QString device4 = adapter + QLatin1String("/dev_70_79_6B_0C_39_55"); + deviceProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(device4)); + deviceProps[QStringLiteral("Adapter")] = QVariant::fromValue(QDBusObjectPath(adapter)); + deviceProps[QStringLiteral("Address")] = QStringLiteral("70:79:6B:0C:39:55"); + deviceProps[QStringLiteral("Name")] = QStringLiteral("TestDevice4"); + deviceProps[QStringLiteral("UUIDs")] = QStringList(QStringLiteral("00001124-0000-1000-8000-00805F9B34FB")); + batteryProps[QStringLiteral("Percentage")] = uchar(100); + deviceProps[QStringLiteral("Battery")] = batteryProps; + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-device"), deviceProps); + + m_manager = new Manager(); + InitManagerJob *initJob = m_manager->init(); + initJob->exec(); + QVERIFY(!initJob->error()); + + for (DevicePtr device : m_manager->devices()) { + QVERIFY(device->battery()); + + BatteryUnit u; + u.device = device; + u.dbusBattery = new org::bluez::Battery1(service, + device->ubi(), + connection, + this); + m_units.append(u); + } + + QCOMPARE(m_manager->adapters().count(), 1); + QCOMPARE(m_manager->devices().count(), 4); +} + +void BatteryTest::cleanupTestCase() +{ + for (const BatteryUnit &unit : m_units) { + delete unit.dbusBattery; + } + + delete m_manager; + + FakeBluez::stop(); +} + +void BatteryTest::getPropertiesTest() +{ + for (const BatteryUnit &unit : m_units) { + QCOMPARE(unit.device->battery()->percentage(), unit.dbusBattery->percentage()); + } +} + +QTEST_MAIN(BatteryTest) diff --git a/autotests/batterytest.h b/autotests/batterytest.h new file mode 100644 index 0000000..f9f73dc --- /dev/null +++ b/autotests/batterytest.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BATTERYTEST_H +#define BATTERYTEST_H + +#include + +#include "bluezbattery1_tst.h" + +#include "manager.h" +#include "device.h" +#include "battery.h" + +class BatteryTest : public QObject +{ + Q_OBJECT + +public: + explicit BatteryTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void getPropertiesTest(); + +private: + struct BatteryUnit + { + BluezQt::DevicePtr device; + org::bluez::Battery1 *dbusBattery; + }; + + BluezQt::Manager *m_manager; + QList m_units; +}; + +#endif // BATTERYTEST_H diff --git a/autotests/fakebluez/CMakeLists.txt b/autotests/fakebluez/CMakeLists.txt index e1126ab..a4227bd 100644 --- a/autotests/fakebluez/CMakeLists.txt +++ b/autotests/fakebluez/CMakeLists.txt @@ -1,27 +1,28 @@ set(fakebluez_SRCS main.cpp fakebluez.cpp testinterface.cpp objectmanager.cpp object.cpp agentmanager.cpp profilemanager.cpp devicemanager.cpp adapterinterface.cpp deviceinterface.cpp + batteryinterface.cpp inputinterface.cpp mediaplayerinterface.cpp mediatransportinterface.cpp obexagentmanager.cpp obexclient.cpp mediainterface.cpp leadvertisingmanagerinterface.cpp gattmanagerinterface.cpp ) add_executable(fakebluez ${fakebluez_SRCS}) target_link_libraries(fakebluez Qt5::Core Qt5::DBus ) diff --git a/autotests/fakebluez/batteryinterface.cpp b/autotests/fakebluez/batteryinterface.cpp new file mode 100644 index 0000000..5e892fb --- /dev/null +++ b/autotests/fakebluez/batteryinterface.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "batteryinterface.h" + +#include + +// BatteryObject +BatteryObject::BatteryObject(const QDBusObjectPath &path, QObject *parent) + : QObject(parent) +{ + QDBusConnection::sessionBus().registerObject(path.path(), this); +} + +// BatteryInterface +BatteryInterface::BatteryInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + setPath(path); + setObjectParent(parent); + setProperties(properties); + setName(QStringLiteral("org.bluez.Battery1")); +} + +uchar BatteryInterface::percentage() const +{ + return Object::property(QStringLiteral("Percentage")).value(); +} diff --git a/autotests/fakebluez/batteryinterface.h b/autotests/fakebluez/batteryinterface.h new file mode 100644 index 0000000..19c1302 --- /dev/null +++ b/autotests/fakebluez/batteryinterface.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BATTERYINTERFACE_H +#define BATTERYINTERFACE_H + +#include "object.h" + +#include + +class QDBusMessage; +class QDBusObjectPath; + +class BatteryObject : public QObject +{ +public: + explicit BatteryObject(const QDBusObjectPath &path, QObject *parent = nullptr); +}; + +class BatteryInterface : public QDBusAbstractAdaptor, public Object +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.Battery1") + Q_PROPERTY(uchar Percentage READ percentage) + +public: + explicit BatteryInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent = nullptr); + + uchar percentage() const; +}; + +#endif // BATTERYINTERFACE_H diff --git a/autotests/fakebluez/deviceinterface.cpp b/autotests/fakebluez/deviceinterface.cpp index 76ac811..ce94fea 100644 --- a/autotests/fakebluez/deviceinterface.cpp +++ b/autotests/fakebluez/deviceinterface.cpp @@ -1,298 +1,312 @@ /* * Copyright (C) 2014-2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "deviceinterface.h" #include "objectmanager.h" +#include "batteryinterface.h" #include "mediaplayerinterface.h" #include "mediatransportinterface.h" #include "inputinterface.h" #include #include #include static const QLatin1String MediaPlayerUuid ("0000110E-0000-1000-8000-00805F9B34FB"); static const QLatin1String MediaTransportUuid ("0000110B-0000-1000-8000-00805F9B34FB"); // DeviceObject DeviceObject::DeviceObject(const QDBusObjectPath &path, QObject *parent) : QObject(parent) { QDBusConnection::sessionBus().registerObject(path.path(), this); } // DeviceInterface DeviceInterface::DeviceInterface(const QDBusObjectPath &path, const QVariantMap &properties, QObject *parent) : QDBusAbstractAdaptor(parent) { setPath(path); setObjectParent(parent); setProperties(properties); setName(QStringLiteral("org.bluez.Device1")); // Alias needs special handling setAlias(properties.value(QStringLiteral("Alias")).toString()); + // Create Battery1 + if (properties.contains(QStringLiteral("Battery"))) { + const QVariantMap &inputProps = qdbus_cast(properties.value(QStringLiteral("Battery"))); + BatteryInterface *input = new BatteryInterface(path, inputProps, parent); + + ObjectManager *manager = ObjectManager::self(); + manager->addObject(input); + + QVariantMap props = properties; + props.remove(QStringLiteral("Battery")); + setProperties(props); + } + // Create Input1 if (properties.contains(QStringLiteral("Input"))) { const QVariantMap &inputProps = qdbus_cast(properties.value(QStringLiteral("Input"))); InputInterface *input = new InputInterface(path, inputProps, parent); ObjectManager *manager = ObjectManager::self(); manager->addObject(input); QVariantMap props = properties; props.remove(QStringLiteral("Input")); setProperties(props); } } QString DeviceInterface::address() const { return Object::property(QStringLiteral("Address")).toString(); } QString DeviceInterface::name() const { return Object::property(QStringLiteral("Name")).toString(); } QString DeviceInterface::alias() const { return Object::property(QStringLiteral("Alias")).toString(); } void DeviceInterface::setAlias(const QString &alias) { Object::changeProperty(QStringLiteral("Alias"), alias.isEmpty() ? name() : alias); } QString DeviceInterface::icon() const { return Object::property(QStringLiteral("Icon")).toString(); } quint32 DeviceInterface::deviceClass() const { return Object::property(QStringLiteral("Class")).toUInt(); } quint16 DeviceInterface::appearance() const { return Object::property(QStringLiteral("Appearance")).toUInt(); } bool DeviceInterface::paired() const { return Object::property(QStringLiteral("Paired")).toBool(); } bool DeviceInterface::connected() const { return Object::property(QStringLiteral("Connected")).toBool(); } bool DeviceInterface::trusted() const { return Object::property(QStringLiteral("Trusted")).toBool(); } void DeviceInterface::setTrusted(bool trusted) { Object::changeProperty(QStringLiteral("Trusted"), trusted); } bool DeviceInterface::blocked() const { return Object::property(QStringLiteral("Blocked")).toBool(); } void DeviceInterface::setBlocked(bool blocked) { Object::changeProperty(QStringLiteral("Blocked"), blocked); } QDBusObjectPath DeviceInterface::adapter() const { return Object::property(QStringLiteral("Adapter")).value(); } bool DeviceInterface::legacyPairing() const { return Object::property(QStringLiteral("LegacyPairing")).toBool(); } qint16 DeviceInterface::rssi() const { return Object::property(QStringLiteral("RSSI")).toInt(); } QStringList DeviceInterface::uuids() const { return Object::property(QStringLiteral("UUIDs")).toStringList(); } QString DeviceInterface::modalias() const { return Object::property(QStringLiteral("Modalias")).toString(); } MediaTransportInterface *DeviceInterface::mediaTransport() const { return m_mediaTransport; } void DeviceInterface::Connect() { if (uuids().contains(MediaPlayerUuid)) { connectMediaPlayer(); } if (uuids().contains(MediaTransportUuid)) { connectMediaTransport(); } Object::changeProperty(QStringLiteral("Connected"), true); } void DeviceInterface::Disconnect() { if (uuids().contains(MediaPlayerUuid)) { disconnectMediaPlayer(); } if (uuids().contains(MediaTransportUuid)) { disconnectMediaTransport(); } Object::changeProperty(QStringLiteral("Connected"), false); } void DeviceInterface::ConnectProfile(const QString &uuid, const QDBusMessage &msg) { if (!uuids().contains(uuid)) { QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.DoesNotExist"), QStringLiteral("Profile UUID not supported")); QDBusConnection::sessionBus().send(error); return; } if (m_connectedUuids.contains(uuid)) { QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.AlreadyConnected"), QStringLiteral("Profile already connected")); QDBusConnection::sessionBus().send(error); return; } if (uuid == MediaPlayerUuid) { connectMediaPlayer(); } else if (uuid == MediaTransportUuid) { connectMediaTransport(); } else { Q_UNIMPLEMENTED(); } Object::changeProperty(QStringLiteral("Connected"), true); } void DeviceInterface::DisconnectProfile(const QString &uuid, const QDBusMessage &msg) { if (!uuids().contains(uuid)) { QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.DoesNotExist"), QStringLiteral("Profile UUID not supported")); QDBusConnection::sessionBus().send(error); return; } if (!m_connectedUuids.contains(uuid)) { QDBusMessage error = msg.createErrorReply(QStringLiteral("org.bluez.Error.NotConnected"), QStringLiteral("Profile not connected")); QDBusConnection::sessionBus().send(error); return; } if (uuid == MediaPlayerUuid) { disconnectMediaPlayer(); } else if (uuid == MediaTransportUuid) { disconnectMediaTransport(); } else { Q_UNIMPLEMENTED(); } Object::changeProperty(QStringLiteral("Connected"), false); } void DeviceInterface::Pair() { Q_UNIMPLEMENTED(); } void DeviceInterface::CancelPairing() { Q_UNIMPLEMENTED(); } void DeviceInterface::connectMediaPlayer() { const QVariantMap &properties = qdbus_cast(Object::property(QStringLiteral("MediaPlayer"))); const QDBusObjectPath &path = properties.value(QStringLiteral("Path")).value(); QVariantMap props = properties; props.remove(QStringLiteral("Path")); MediaPlayerObject *mediaPlayerObj = new MediaPlayerObject(path); m_mediaPlayer = new MediaPlayerInterface(path, props, mediaPlayerObj); ObjectManager *manager = ObjectManager::self(); manager->addObject(m_mediaPlayer); manager->addAutoDeleteObject(mediaPlayerObj); m_connectedUuids.append(MediaPlayerUuid); } void DeviceInterface::disconnectMediaPlayer() { ObjectManager *manager = ObjectManager::self(); manager->removeObject(m_mediaPlayer); m_connectedUuids.removeOne(MediaPlayerUuid); m_mediaPlayer = nullptr; } void DeviceInterface::connectMediaTransport() { const QVariantMap &properties = qdbus_cast(Object::property(QStringLiteral("MediaTransport"))); const QDBusObjectPath &path = properties.value(QStringLiteral("Path")).value(); QVariantMap props = properties; props.remove(QStringLiteral("Path")); MediaTransportObject *transportObj = new MediaTransportObject(path); m_mediaTransport = new MediaTransportInterface(path, props, transportObj); ObjectManager *manager = ObjectManager::self(); manager->addObject(m_mediaTransport); manager->addAutoDeleteObject(transportObj); m_connectedUuids.append(MediaTransportUuid); } void DeviceInterface::disconnectMediaTransport() { ObjectManager *manager = ObjectManager::self(); manager->removeObject(m_mediaTransport); m_connectedUuids.removeOne(MediaTransportUuid); m_mediaTransport = nullptr; } diff --git a/autotests/interfaces/org.bluez.Battery1.xml b/autotests/interfaces/org.bluez.Battery1.xml new file mode 100644 index 0000000..1fcbef8 --- /dev/null +++ b/autotests/interfaces/org.bluez.Battery1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41bdfe3..bd4e72c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,201 +1,203 @@ set(bluezqt_SRCS a2dp-codecs.c manager.cpp manager_p.cpp adapter.cpp adapter_p.cpp + battery.cpp device.cpp device_p.cpp gattapplication.cpp gattapplication_p.cpp gattcharacteristic.cpp gattcharacteristic_p.cpp gattcharacteristicadaptor.cpp gattmanager.cpp gattmanager_p.cpp gattservice.cpp gattservice_p.cpp gattserviceadaptor.cpp input.cpp leadvertisement.cpp leadvertisement_p.cpp leadvertisementadaptor.cpp leadvertisingmanager.cpp media.cpp mediaendpoint.cpp mediaendpoint_p.cpp mediaendpointadaptor.cpp mediaplayer.cpp mediaplayer_p.cpp mediaplayertrack.cpp mediatransport.cpp mediatransport_p.cpp objectmanageradaptor.cpp devicesmodel.cpp job.cpp initmanagerjob.cpp initobexmanagerjob.cpp utils.cpp agent.cpp agentadaptor.cpp profile.cpp profileadaptor.cpp pendingcall.cpp request.cpp rfkill.cpp obexmanager.cpp obexmanager_p.cpp obexagent.cpp obexagentadaptor.cpp obextransfer.cpp obexsession.cpp obexobjectpush.cpp obexfiletransfer.cpp obexfiletransferentry.cpp ) ecm_qt_declare_logging_category(bluezqt_SRCS HEADER debug.h IDENTIFIER BLUEZQT CATEGORY_NAME org.kde.bluez) set(dbusobjectmanager_xml ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.ObjectManager.xml) set_source_files_properties(${dbusobjectmanager_xml} PROPERTIES INCLUDE "bluezqt_dbustypes.h") qt5_add_dbus_interface(bluezqt_SRCS ${dbusobjectmanager_xml} dbusobjectmanager) set(obexfiletransfer1_xml ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.FileTransfer1.xml) set_source_files_properties(${obexfiletransfer1_xml} PROPERTIES INCLUDE "bluezqt_dbustypes.h") qt5_add_dbus_interface(bluezqt_SRCS ${obexfiletransfer1_xml} obexfiletransfer1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.Properties.xml dbusproperties) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Adapter1.xml bluezadapter1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.AgentManager1.xml bluezagentmanager1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Battery1.xml bluezbattery1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattCharacteristic1.xml bluezgattcharacteristic1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattManager1.xml bluezgattmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.ProfileManager1.xml bluezprofilemanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Device1.xml bluezdevice1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.LEAdvertisement1.xml bluezleadvertisement1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.LEAdvertisingManager1.xml bluezleadvertisingmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Media1.xml bluezmedia1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaEndpoint1.xml bluezmediaendpoint1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaPlayer1.xml bluezmediaplayer1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.AgentManager1.xml obexagentmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.Client1.xml obexclient1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.Transfer1.xml obextransfer1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.Session1.xml obexsession1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.obex.ObjectPush1.xml obexobjectpush1) add_library(KF5BluezQt ${bluezqt_SRCS}) add_library(KF5::BluezQt ALIAS KF5BluezQt) ecm_generate_export_header(KF5BluezQt BASE_NAME BluezQt GROUP_BASE_NAME KF VERSION ${KF5_VERSION} DEPRECATED_BASE_VERSION 0 DEPRECATION_VERSIONS 5.57 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) target_include_directories(KF5BluezQt INTERFACE "$") target_link_libraries(KF5BluezQt PUBLIC Qt5::Core PRIVATE Qt5::DBus Qt5::Network ) set_target_properties(KF5BluezQt PROPERTIES VERSION ${BLUEZQT_VERSION_STRING} SOVERSION ${BLUEZQT_SOVERSION} EXPORT_NAME "BluezQt" ) ecm_generate_headers(BluezQt_CamelCase_HEADERS HEADER_NAMES Types Manager Adapter Device GattApplication GattCharacteristic GattManager GattService Input LEAdvertisement LEAdvertisingManager Media MediaEndpoint MediaPlayer MediaPlayerTrack DevicesModel Job InitManagerJob InitObexManagerJob Services Agent Profile PendingCall Request ObexManager ObexAgent ObexTransfer ObexSession ObexObjectPush ObexFileTransfer ObexFileTransferEntry REQUIRED_HEADERS BluezQt_HEADERS PREFIX BluezQt ) # Install files install(TARGETS KF5BluezQt EXPORT KF5BluezQtTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${BluezQt_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/BluezQt/BluezQt COMPONENT Devel) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bluezqt_export.h ${BluezQt_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/BluezQt/bluezqt COMPONENT Devel) if(BUILD_QCH) ecm_add_qch( KF5BluezQt_QCH NAME BluezQt BASE_NAME KF5BluezQt VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${BluezQt_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS Qt5Core_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS BLUEZQT_EXPORT BLUEZQT_DEPRECATED BLUEZQT_DEPRECATED_EXPORT "BLUEZQT_DEPRECATED_VERSION(x, y, t)" TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() include(ECMGeneratePriFile) ecm_generate_pri_file( BASE_NAME BluezQt LIB_NAME KF5BluezQt DEPS "core" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/BluezQt ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/battery.cpp b/src/battery.cpp new file mode 100644 index 0000000..de6ed73 --- /dev/null +++ b/src/battery.cpp @@ -0,0 +1,80 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "battery.h" +#include "battery_p.h" +#include "utils.h" +#include "macros.h" + +#include + +namespace BluezQt +{ + +BatteryPrivate::BatteryPrivate(const QString &path, const QVariantMap &properties) + : QObject() + , m_path(path) +{ + // Init properties + m_percentage = properties.value(QStringLiteral("Percentage")).toInt(); +} + +void BatteryPrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) +{ + Q_UNUSED(invalidated) + + if (interface != Strings::orgBluezBattery1()) { + return; + } + + QVariantMap::const_iterator i; + for (i = changed.constBegin(); i != changed.constEnd(); ++i) { + const QVariant &value = i.value(); + const QString &property = i.key(); + + if (property == QLatin1String("Percentage")) { + PROPERTY_CHANGED2(m_percentage, value.toInt(), percentageChanged) + } + } +} + +Battery::Battery(const QString &path, const QVariantMap &properties) + : d(new BatteryPrivate(path, properties)) +{ +} + +Battery::~Battery() +{ + delete d; +} + +BatteryPtr Battery::toSharedPtr() const +{ + return d->q.toStrongRef(); +} + +int Battery::percentage() const +{ + return d->m_percentage; +} + +} // namespace BluezQt diff --git a/src/battery.h b/src/battery.h new file mode 100644 index 0000000..381b7a2 --- /dev/null +++ b/src/battery.h @@ -0,0 +1,83 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_BATTERY_H +#define BLUEZQT_BATTERY_H + +#include + +#include "types.h" +#include "bluezqt_export.h" + +namespace BluezQt +{ + +/** + * @class BluezQt::Battery battery.h + * + * %Device battery. + * + * This class represents a battery interface. + */ +class BLUEZQT_EXPORT Battery : public QObject +{ + Q_OBJECT + Q_PROPERTY(int percentage READ percentage NOTIFY percentageChanged) + +public: + /** + * Destroys a Battery object. + */ + ~Battery(); + + /** + * Returns a shared pointer from this. + * + * @return BatteryPtr + */ + BatteryPtr toSharedPtr() const; + + /** + * Returns the battery percentage. + * + * @return battery percentage + */ + int percentage() const; + +Q_SIGNALS: + /** + * Indicates that battery's percentage has changed. + */ + void percentageChanged(int percentage); + +private: + explicit Battery(const QString &path, const QVariantMap &properties); + + class BatteryPrivate *const d; + + friend class BatteryPrivate; + friend class DevicePrivate; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_BATTERY_H diff --git a/src/imports/declarativedevicesmodel.h b/src/battery_p.h similarity index 50% copy from src/imports/declarativedevicesmodel.h copy to src/battery_p.h index 8d034b4..83fdd0b 100644 --- a/src/imports/declarativedevicesmodel.h +++ b/src/battery_p.h @@ -1,58 +1,50 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2014 David Rosca + * Copyright (C) 2019 Kai Uwe Broulik * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ -#ifndef DECLARATIVEDEVICESMODEL_H -#define DECLARATIVEDEVICESMODEL_H +#ifndef BLUEZQT_BATTERY_P_H +#define BLUEZQT_BATTERY_P_H -#include +#include -#include "devicesmodel.h" +#include "battery.h" -class DeclarativeManager; +namespace BluezQt +{ -class DeclarativeDevicesModel : public QSortFilterProxyModel +class BatteryPrivate : public QObject { Q_OBJECT - Q_PROPERTY(DeclarativeManager* manager READ manager WRITE setManager) public: - enum DeclarativeDeviceRoles { - DeviceRole = BluezQt::DevicesModel::LastRole + 1, - AdapterRole = BluezQt::DevicesModel::LastRole + 2, - MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3 - }; - - explicit DeclarativeDevicesModel(QObject *parent = nullptr); + explicit BatteryPrivate(const QString &path, const QVariantMap &properties); - DeclarativeManager *manager() const; - void setManager(DeclarativeManager *manager); + void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); - QHash roleNames() const override; - QVariant data(const QModelIndex &index, int role) const override; + QWeakPointer q; -private: - DeclarativeManager *m_manager; - BluezQt::DevicesModel *m_model; + QString m_path; + int m_percentage = 0; }; -#endif // DECLARATIVEMANAGER_H +} // namespace BluezQt +#endif // BLUEZQT_BATTERY_P_H diff --git a/src/device.cpp b/src/device.cpp index 92567ca..56d44fa 100644 --- a/src/device.cpp +++ b/src/device.cpp @@ -1,303 +1,308 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "device.h" #include "device_p.h" #include "pendingcall.h" #include "utils.h" namespace BluezQt { Device::Device(const QString &path, const QVariantMap &properties, AdapterPtr adapter) : QObject() , d(new DevicePrivate(path, properties, adapter)) { } Device::~Device() { delete d; } DevicePtr Device::toSharedPtr() const { return d->q.toStrongRef(); } QString Device::ubi() const { return d->m_bluezDevice->path(); } QString Device::address() const { return d->m_address; } QString Device::name() const { return d->m_alias; } PendingCall *Device::setName(const QString &name) { return new PendingCall(d->setDBusProperty(QStringLiteral("Alias"), name), PendingCall::ReturnVoid, this); } QString Device::friendlyName() const { if (name().isEmpty() || name() == remoteName()) { return name(); } if (remoteName().isEmpty()) { return name(); } return QStringLiteral("%1 (%2)").arg(name(), remoteName()); } QString Device::remoteName() const { return d->m_name; } quint32 Device::deviceClass() const { return d->m_deviceClass; } Device::Type Device::type() const { if (deviceClass() == 0) { return appearanceToType(appearance()); } return classToType(d->m_deviceClass); } quint16 Device::appearance() const { return d->m_appearance; } QString Device::icon() const { switch (type()) { case Headset: return QStringLiteral("audio-headset"); case Headphones: return QStringLiteral("audio-headphones"); default: return d->m_icon.isEmpty() ? QStringLiteral("preferences-system-bluetooth") : d->m_icon; } } bool Device::isPaired() const { return d->m_paired; } bool Device::isTrusted() const { return d->m_trusted; } PendingCall *Device::setTrusted(bool trusted) { return new PendingCall(d->setDBusProperty(QStringLiteral("Trusted"), trusted), PendingCall::ReturnVoid, this); } bool Device::isBlocked() const { return d->m_blocked; } PendingCall *Device::setBlocked(bool blocked) { return new PendingCall(d->setDBusProperty(QStringLiteral("Blocked"), blocked), PendingCall::ReturnVoid, this); } bool Device::hasLegacyPairing() const { return d->m_legacyPairing; } qint16 Device::rssi() const { return d->m_rssi; } bool Device::isConnected() const { return d->m_connected; } QStringList Device::uuids() const { return d->m_uuids; } QString Device::modalias() const { return d->m_modalias; } +BatteryPtr Device::battery() const +{ + return d->m_battery; +} + InputPtr Device::input() const { return d->m_input; } MediaPlayerPtr Device::mediaPlayer() const { return d->m_mediaPlayer; } MediaTransportPtr Device::mediaTransport() const { return d->m_mediaTransport; } AdapterPtr Device::adapter() const { return d->m_adapter; } QString Device::typeToString(Device::Type type) { switch (type) { case Device::Phone: return QStringLiteral("phone"); case Device::Modem: return QStringLiteral("modem"); case Device::Computer: return QStringLiteral("computer"); case Device::Network: return QStringLiteral("network"); case Device::Headset: return QStringLiteral("headset"); case Device::Headphones: return QStringLiteral("headphones"); case Device::AudioVideo: return QStringLiteral("audiovideo"); case Device::Keyboard: return QStringLiteral("keyboard"); case Device::Mouse: return QStringLiteral("mouse"); case Device::Joypad: return QStringLiteral("joypad"); case Device::Tablet: return QStringLiteral("tablet"); case Device::Peripheral: return QStringLiteral("peripheral"); case Device::Camera: return QStringLiteral("camera"); case Device::Printer: return QStringLiteral("printer"); case Device::Imaging: return QStringLiteral("imaging"); case Device::Wearable: return QStringLiteral("wearable"); case Device::Toy: return QStringLiteral("toy"); case Device::Health: return QStringLiteral("health"); default: return QStringLiteral("uncategorized"); } } Device::Type Device::stringToType(const QString &typeString) { if (typeString == QLatin1String("phone")) { return Device::Phone; } else if (typeString == QLatin1String("modem")) { return Device::Modem; } else if (typeString == QLatin1String("computer")) { return Device::Computer; } else if (typeString == QLatin1String("network")) { return Device::Network; } else if (typeString == QLatin1String("headset")) { return Device::Headset; } else if (typeString == QLatin1String("headphones")) { return Device::Headphones; } else if (typeString == QLatin1String("audio")) { return Device::AudioVideo; } else if (typeString == QLatin1String("keyboard")) { return Device::Keyboard; } else if (typeString == QLatin1String("mouse")) { return Device::Mouse; } else if (typeString == QLatin1String("joypad")) { return Device::Joypad; } else if (typeString == QLatin1String("tablet")) { return Device::Tablet; } else if (typeString == QLatin1String("peripheral")) { return Device::Peripheral; } else if (typeString == QLatin1String("camera")) { return Device::Camera; } else if (typeString == QLatin1String("printer")) { return Device::Printer; } else if (typeString == QLatin1String("imaging")) { return Device::Imaging; } else if (typeString == QLatin1String("wearable")) { return Device::Wearable; } else if (typeString == QLatin1String("toy")) { return Device::Toy; } else if (typeString == QLatin1String("health")) { return Device::Health; } return Device::Uncategorized; } PendingCall *Device::connectToDevice() { return new PendingCall(d->m_bluezDevice->Connect(), PendingCall::ReturnVoid, this); } PendingCall *Device::disconnectFromDevice() { return new PendingCall(d->m_bluezDevice->Disconnect(), PendingCall::ReturnVoid, this); } PendingCall *Device::connectProfile(const QString &uuid) { return new PendingCall(d->m_bluezDevice->ConnectProfile(uuid), PendingCall::ReturnVoid, this); } PendingCall *Device::disconnectProfile(const QString &uuid) { return new PendingCall(d->m_bluezDevice->DisconnectProfile(uuid), PendingCall::ReturnVoid, this); } PendingCall *Device::pair() { return new PendingCall(d->m_bluezDevice->Pair(), PendingCall::ReturnVoid, this); } PendingCall *Device::cancelPairing() { return new PendingCall(d->m_bluezDevice->CancelPairing(), PendingCall::ReturnVoid, this); } } // namespace BluezQt diff --git a/src/device.h b/src/device.h index c56689e..ea4bb27 100644 --- a/src/device.h +++ b/src/device.h @@ -1,539 +1,553 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2014-2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef BLUEZQT_DEVICE_H #define BLUEZQT_DEVICE_H #include #include "types.h" #include "bluezqt_export.h" namespace BluezQt { class Adapter; class PendingCall; /** * @class BluezQt::Device device.h * * Bluetooth device. * * This class represents a Bluetooth device. */ class BLUEZQT_EXPORT Device : public QObject { Q_OBJECT Q_PROPERTY(QString ubi READ ubi) Q_PROPERTY(QString address READ address NOTIFY addressChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString friendlyName READ friendlyName NOTIFY friendlyNameChanged) Q_PROPERTY(QString remoteName READ remoteName NOTIFY remoteNameChanged) Q_PROPERTY(quint32 deviceClass READ deviceClass NOTIFY deviceClassChanged) Q_PROPERTY(Type type READ type NOTIFY typeChanged) Q_PROPERTY(quint16 appearance READ appearance NOTIFY appearanceChanged) Q_PROPERTY(QString icon READ icon NOTIFY iconChanged) Q_PROPERTY(bool paired READ isPaired NOTIFY pairedChanged) Q_PROPERTY(bool trusted READ isTrusted WRITE setTrusted NOTIFY trustedChanged) Q_PROPERTY(bool blocked READ isBlocked WRITE setBlocked NOTIFY blockedChanged) Q_PROPERTY(bool legacyPairing READ hasLegacyPairing NOTIFY legacyPairingChanged) Q_PROPERTY(qint16 rssi READ rssi NOTIFY rssiChanged) Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged) Q_PROPERTY(QStringList uuids READ uuids NOTIFY uuidsChanged) Q_PROPERTY(QString modalias READ modalias NOTIFY modaliasChanged) + Q_PROPERTY(BatteryPtr battery READ battery NOTIFY batteryChanged) Q_PROPERTY(InputPtr input READ input NOTIFY inputChanged) Q_PROPERTY(MediaPlayerPtr mediaPlayer READ mediaPlayer NOTIFY mediaPlayerChanged) Q_PROPERTY(MediaTransportPtr mediaTransport READ mediaTransport NOTIFY mediaTransportChanged) Q_PROPERTY(AdapterPtr adapter READ adapter) public: /** * %Device types. */ enum Type { /** The device is a phone. */ Phone, /** The device is a modem. */ Modem, /** The device is a computer. */ Computer, /** The device is a network. */ Network, /** The device is a headset. */ Headset, /** The device is a headphones. */ Headphones, /** The device is an uncategorized audio video device. */ AudioVideo, /** The device is a keyboard. */ Keyboard, /** The device is a mouse. */ Mouse, /** The device is a joypad. */ Joypad, /** The device is a graphics tablet (input device). */ Tablet, /** The deivce is an uncategorized peripheral device. */ Peripheral, /** The device is a camera. */ Camera, /** The device is a printer. */ Printer, /** The device is an uncategorized imaging device. */ Imaging, /** The device is a wearable device. */ Wearable, /** The device is a toy. */ Toy, /** The device is a health device. */ Health, /** The device is not of any of the known types. */ Uncategorized }; Q_ENUM(Type) /** * Destroys a Device object. */ ~Device(); /** * Returns a shared pointer from this. * * @return DevicePtr */ DevicePtr toSharedPtr() const; /** * Returns an UBI of the device. * * Example UBI: "/org/bluez/hci0/dev_40_79_6A_0C_39_75" * * @return UBI of device */ QString ubi() const; /** * Returns an address of the device. * * Example address: "40:79:6A:0C:39:75" * * @return address of device */ QString address() const; /** * Returns a name of the device. * * If the name of the device wasn't previously changed, * remoteName is returned. * * @return name of device */ QString name() const; /** * Sets the name of the device. * * @param name name for device * @return void pending call */ PendingCall *setName(const QString &name); /** * Returns a friendly name of the device. * * Friendly name is a string "name (remoteName)". * If the remoteName is same as name, it returns just name. * * @return friendly name of device */ QString friendlyName() const; /** * Returns a remote name of the device. * * @return remote name of device */ QString remoteName() const; /** * Returns a class of the device. * * In case of Bluetooth Low Energy only devices, * device class is invalid (0). * * @see type() const * * @return class of device */ quint32 deviceClass() const; /** * Returns a type of the device. * * Type of device is deduced from its class (for Bluetooth Classic devices) * or its appearance (for Bluetooth Low Energy devices). * * @see deviceClass() const * @see appearance() const * * @return type of device */ Device::Type type() const; /** * Returns an appearance of the device. * * @return appearance of device */ quint16 appearance() const; /** * Returns an icon name of the device. * * In case the icon is empty, "preferences-system-bluetooth" is returned. * * @return icon name of device */ QString icon() const; /** * Returns whether the device is paired. * * @return true if device is paired */ bool isPaired() const; /** * Returns whether the device is trusted. * * @return true if device is trusted */ bool isTrusted() const; /** * Sets the trusted state of the device. * * @param trusted trusted state * @return void pending call */ PendingCall *setTrusted(bool trusted); /** * Returns whether the device is blocked. * * @return true if device is blocked */ bool isBlocked() const; /** * Sets the blocked state of the device. * * @param blocked blocked state * @return void pending call */ PendingCall *setBlocked(bool blocked); /** * Returns whether the device has legacy pairing. * * @return true if device has legacy pairing */ bool hasLegacyPairing() const; /** * Returns Received Signal Strength Indicator of the device. * * The bigger value indicates better signal strength. * * @note RSSI is only updated during discovery. * * @return RSSI of device */ qint16 rssi() const; /** * Returns whether the device is connected. * * @return true if connected */ bool isConnected() const; /** * Returns UUIDs of supported services by the device. * * UUIDs will always be returned in uppercase. * * @return UUIDs of supported services */ QStringList uuids() const; /** * Returns remote device ID in modalias format. * * @return device modalias */ QString modalias() const; + /** + * Returns the battery interface for the device. + * + * @return null if device has no battery + * @since 5.66 + */ + BatteryPtr battery() const; + /** * Returns the input interface for the device. * * Only input devices will have valid input interface. * * @return null if device have no input */ InputPtr input() const; /** * Returns the media player interface for the device. * * Only devices with connected appropriate profile will * have valid media player interface. * * @return null if device have no media player */ MediaPlayerPtr mediaPlayer() const; /** * Returns the media transport interface for the device. * * Only devices with connected appropriate profile will * have valid media transport interface. * * @return null if device have no media transport */ MediaTransportPtr mediaTransport() const; /** * Returns an adapter that discovered this device. * * @return adapter of device */ AdapterPtr adapter() const; /** * Returns a string for device type. * * @param type device type * @return device type string */ static QString typeToString(Device::Type type); /** * Returns a device type for string. * * @param typeString type string * @return device type */ static Device::Type stringToType(const QString &typeString); public Q_SLOTS: /** * Connects all auto-connectable profiles of the device. * * This method indicates success if at least one profile was connected. * * Possible errors: PendingCall::NotReady, PendingCall::Failed, * PendingCall::InProgress, PendingCall::AlreadyConnected * * @return void pending call */ PendingCall *connectToDevice(); /** * Disconnects all connected profiles of the device. * * This method can be used to cancel not-yet finished connectDevice() call. * * Possible errors: PendingCall::NotConnected * * @return void pending call */ PendingCall *disconnectFromDevice(); /** * Connects a specific profile of the device. * * Possible errors: PendingCall::DoesNotExist, PendingCall::AlreadyConnected, * PendingCall::ConnectFailed * * @param uuid service UUID * @return void pending call */ PendingCall *connectProfile(const QString &uuid); /** * Disconnects a specific profile of the device. * * Possible errors: PendingCall::DoesNotExist, PendingCall::Failed, * PendingCall::NotConnected, PendingCall::NotSupported * * @param uuid service UUID * @return void pending call */ PendingCall *disconnectProfile(const QString &uuid); /** * Initiates a pairing with the device. * * Possible errors: PendingCall::InvalidArguments, PendingCall::Failed, * PendingCall::AlreadyExists, PendingCall::AuthenticationCanceled, * PendingCall::AuthenticationFailed, PendingCall::AuthenticationRejected, * PendingCall::AuthenticationTimeout, PendingCall::ConnectionAttemptFailed * * @return void pending call */ PendingCall *pair(); /** * Cancels a pairing with the device. * * This method can be used to cancel pairing operation initiated with pair(). * * Possible errors: PendingCall::DoesNotExist, PendingCall::Failed * * @return void pending call */ PendingCall *cancelPairing(); Q_SIGNALS: /** * Indicates that the device was removed. */ void deviceRemoved(DevicePtr device); /** * Indicates that at least one of the device's properties have changed. */ void deviceChanged(DevicePtr device); /** * Indicates that device's name have changed. */ void nameChanged(const QString &name); /** * Indicates that device's address have changed. */ void addressChanged(const QString &address); /** * Indicates that device's friendly name have changed. */ void friendlyNameChanged(const QString &friendlyName); /** * Indicates that device's remote name have changed. */ void remoteNameChanged(const QString &remoteName); /** * Indicates that device's class have changed. */ void deviceClassChanged(quint32 deviceClass); /** * Indicates that device's type have changed. */ void typeChanged(Type type); /** * Indicates that device's appearance have changed. */ void appearanceChanged(quint16 appearance); /** * Indicates that device's icon have changed. */ void iconChanged(const QString &icon); /** * Indicates that device's paired state have changed. */ void pairedChanged(bool paired); /** * Indicates that device's trusted state have changed. */ void trustedChanged(bool trusted); /** * Indicates that device's blocked state have changed. */ void blockedChanged(bool blocked); /** * Indicates that device's legacy pairing state have changed. */ void legacyPairingChanged(bool legacyPairing); /** * Indicates that device's RSSI have changed. */ void rssiChanged(qint16 rssi); /** * Indicates that device's connected state have changed. */ void connectedChanged(bool connected); /** * Indicates that device's UUIDs have changed. */ void uuidsChanged(const QStringList &uuids); /** * Indicates that device's modalias have changed. */ void modaliasChanged(const QString &modalias); + /** + * Indicates that device's battery has changed. + */ + void batteryChanged(BatteryPtr battery); + /** * Indicates that device's input have changed. */ void inputChanged(InputPtr input); /** * Indicates that device's media player have changed. */ void mediaPlayerChanged(MediaPlayerPtr mediaPlayer); /** * Indicates that device's media transport have changed. */ void mediaTransportChanged(MediaTransportPtr mediaTransport); private: explicit Device(const QString &path, const QVariantMap &properties, AdapterPtr adapter); class DevicePrivate *const d; friend class DevicePrivate; friend class ManagerPrivate; friend class Adapter; }; } // namespace BluezQt #endif // BLUEZQT_DEVICE_H diff --git a/src/device_p.cpp b/src/device_p.cpp index aa8d792..8935799 100644 --- a/src/device_p.cpp +++ b/src/device_p.cpp @@ -1,245 +1,258 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "device_p.h" #include "device.h" #include "adapter.h" +#include "battery.h" +#include "battery_p.h" #include "input.h" #include "input_p.h" #include "mediaplayer.h" #include "mediaplayer_p.h" #include "mediatransport.h" #include "mediatransport_p.h" #include "utils.h" #include "macros.h" namespace BluezQt { static const qint16 INVALID_RSSI = -32768; // qint16 minimum DevicePrivate::DevicePrivate(const QString &path, const QVariantMap &properties, const AdapterPtr &adapter) : QObject() , m_dbusProperties(nullptr) , m_deviceClass(0) , m_appearance(0) , m_paired(false) , m_trusted(false) , m_blocked(false) , m_legacyPairing(false) , m_rssi(INVALID_RSSI) , m_connected(false) , m_adapter(adapter) { m_bluezDevice = new BluezDevice(Strings::orgBluez(), path, DBusConnection::orgBluez(), this); init(properties); } void DevicePrivate::init(const QVariantMap &properties) { m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezDevice->path(), DBusConnection::orgBluez(), this); // Init properties m_address = properties.value(QStringLiteral("Address")).toString(); m_name = properties.value(QStringLiteral("Name")).toString(); m_alias = properties.value(QStringLiteral("Alias")).toString(); m_deviceClass = properties.value(QStringLiteral("Class")).toUInt(); m_appearance = properties.value(QStringLiteral("Appearance")).toUInt(); m_icon = properties.value(QStringLiteral("Icon")).toString(); m_paired = properties.value(QStringLiteral("Paired")).toBool(); m_trusted = properties.value(QStringLiteral("Trusted")).toBool(); m_blocked = properties.value(QStringLiteral("Blocked")).toBool(); m_legacyPairing = properties.value(QStringLiteral("LegacyPairing")).toBool(); m_rssi = properties.value(QStringLiteral("RSSI")).toInt(); m_connected = properties.value(QStringLiteral("Connected")).toBool(); m_uuids = stringListToUpper(properties.value(QStringLiteral("UUIDs")).toStringList()); m_modalias = properties.value(QStringLiteral("Modalias")).toString(); if (!m_rssi) { m_rssi = INVALID_RSSI; } } void DevicePrivate::interfacesAdded(const QString &path, const QVariantMapMap &interfaces) { bool changed = false; QVariantMapMap::const_iterator it; for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) { - if (it.key() == Strings::orgBluezInput1()) { + if (it.key() == Strings::orgBluezBattery1()) { + m_battery = BatteryPtr(new Battery(path, it.value())); + m_battery->d->q = m_battery.toWeakRef(); + Q_EMIT q.lock()->batteryChanged(m_battery); + changed = true; + } else if (it.key() == Strings::orgBluezInput1()) { m_input = InputPtr(new Input(path, it.value())); m_input->d->q = m_input.toWeakRef(); Q_EMIT q.lock()->inputChanged(m_input); changed = true; } else if (it.key() == Strings::orgBluezMediaPlayer1()) { m_mediaPlayer = MediaPlayerPtr(new MediaPlayer(path, it.value())); m_mediaPlayer->d->q = m_mediaPlayer.toWeakRef(); Q_EMIT q.lock()->mediaPlayerChanged(m_mediaPlayer); changed = true; } else if (it.key() == Strings::orgBluezMediaTransport1()) { m_mediaTransport = MediaTransportPtr(new MediaTransport(path, it.value())); m_mediaTransport->d->q = m_mediaTransport.toWeakRef(); Q_EMIT q.lock()->mediaTransportChanged(m_mediaTransport); changed = true; } } if (changed) { Q_EMIT q.lock()->deviceChanged(q.toStrongRef()); } } void DevicePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces) { bool changed = false; for (const QString &interface : interfaces) { - if (interface == Strings::orgBluezInput1() && m_input && m_input->d->m_path == path) { + if (interface == Strings::orgBluezBattery1() && m_battery && m_battery->d->m_path == path) { + m_battery.clear(); + Q_EMIT q.lock()->batteryChanged(m_battery); + changed = true; + } else if (interface == Strings::orgBluezInput1() && m_input && m_input->d->m_path == path) { m_input.clear(); Q_EMIT q.lock()->inputChanged(m_input); changed = true; } else if (interface == Strings::orgBluezMediaPlayer1() && m_mediaPlayer && m_mediaPlayer->d->m_path == path) { m_mediaPlayer.clear(); Q_EMIT q.lock()->mediaPlayerChanged(m_mediaPlayer); changed = true; } else if (interface == Strings::orgBluezMediaTransport1() && m_mediaTransport && m_mediaTransport->d->m_path == path) { m_mediaTransport.clear(); Q_EMIT q.lock()->mediaTransportChanged(m_mediaTransport); changed = true; } } if (changed) { Q_EMIT q.lock()->deviceChanged(q.toStrongRef()); } } QDBusPendingReply<> DevicePrivate::setDBusProperty(const QString &name, const QVariant &value) { return m_dbusProperties->Set(Strings::orgBluezDevice1(), name, QDBusVariant(value)); } void DevicePrivate::propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated) { - if (interface == Strings::orgBluezInput1() && m_input) { + if (interface == Strings::orgBluezBattery1() && m_battery) { + m_battery->d->propertiesChanged(interface, changed, invalidated); + } else if (interface == Strings::orgBluezInput1() && m_input) { m_input->d->propertiesChanged(interface, changed, invalidated); } else if (interface == Strings::orgBluezMediaPlayer1() && m_mediaPlayer) { m_mediaPlayer->d->propertiesChanged(interface, changed, invalidated); } else if (interface != Strings::orgBluezDevice1()) { return; } QVariantMap::const_iterator i; for (i = changed.constBegin(); i != changed.constEnd(); ++i) { const QVariant &value = i.value(); const QString &property = i.key(); if (property == QLatin1String("Name")) { namePropertyChanged(value.toString()); } else if (property == QLatin1String("Address")) { addressPropertyChanged(value.toString()); } else if (property == QLatin1String("Alias")) { aliasPropertyChanged(value.toString()); } else if (property == QLatin1String("Class")) { classPropertyChanged(value.toUInt()); } else if (property == QLatin1String("Appearance")) { PROPERTY_CHANGED(m_appearance, toUInt, appearanceChanged); } else if (property == QLatin1String("Icon")) { PROPERTY_CHANGED(m_icon, toString, iconChanged); } else if (property == QLatin1String("Paired")) { PROPERTY_CHANGED(m_paired, toBool, pairedChanged); } else if (property == QLatin1String("Trusted")) { PROPERTY_CHANGED(m_trusted, toBool, trustedChanged); } else if (property == QLatin1String("Blocked")) { PROPERTY_CHANGED(m_blocked, toBool, blockedChanged); } else if (property == QLatin1String("LegacyPairing")) { PROPERTY_CHANGED(m_legacyPairing, toBool, legacyPairingChanged); } else if (property == QLatin1String("RSSI")) { PROPERTY_CHANGED(m_rssi, toInt, rssiChanged); } else if (property == QLatin1String("Connected")) { PROPERTY_CHANGED(m_connected, toBool, connectedChanged); } else if (property == QLatin1String("Modalias")) { PROPERTY_CHANGED(m_modalias, toString, modaliasChanged); } else if (property == QLatin1String("UUIDs")) { PROPERTY_CHANGED2(m_uuids, stringListToUpper(value.toStringList()), uuidsChanged); } } for (const QString &property : invalidated) { if (property == QLatin1String("Name")) { namePropertyChanged(QString()); } else if (property == QLatin1String("Class")) { classPropertyChanged(0); } else if (property == QLatin1String("Appearance")) { PROPERTY_INVALIDATED(m_appearance, 0, appearanceChanged); } else if (property == QLatin1String("Icon")) { PROPERTY_INVALIDATED(m_icon, QString(), iconChanged); } else if (property == QLatin1String("RSSI")) { PROPERTY_INVALIDATED(m_rssi, INVALID_RSSI, rssiChanged); } else if (property == QLatin1String("Modalias")) { PROPERTY_INVALIDATED(m_modalias, QString(), modaliasChanged); } else if (property == QLatin1String("UUIDs")) { PROPERTY_INVALIDATED(m_uuids, QStringList(), uuidsChanged); } } Q_EMIT q.lock()->deviceChanged(q.toStrongRef()); } void DevicePrivate::namePropertyChanged(const QString &value) { if (m_name != value) { m_name = value; Q_EMIT q.lock()->remoteNameChanged(m_name); Q_EMIT q.lock()->friendlyNameChanged(q.lock()->friendlyName()); } } void DevicePrivate::addressPropertyChanged(const QString &value) { if (m_address != value) { m_address = value; Q_EMIT q.lock()->addressChanged(m_address); } } void DevicePrivate::aliasPropertyChanged(const QString &value) { if (m_alias != value) { m_alias = value; Q_EMIT q.lock()->nameChanged(m_alias); Q_EMIT q.lock()->friendlyNameChanged(q.lock()->friendlyName()); } } void DevicePrivate::classPropertyChanged(quint32 value) { if (m_deviceClass != value) { m_deviceClass = value; Q_EMIT q.lock()->deviceClassChanged(m_deviceClass); Q_EMIT q.lock()->typeChanged(q.lock()->type()); } } } // namespace BluezQt diff --git a/src/device_p.h b/src/device_p.h index 684c96f..07e940c 100644 --- a/src/device_p.h +++ b/src/device_p.h @@ -1,85 +1,86 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef BLUEZQT_DEVICE_P_H #define BLUEZQT_DEVICE_P_H #include #include #include "types.h" #include "bluezdevice1.h" #include "dbusproperties.h" #include "bluezqt_dbustypes.h" namespace BluezQt { typedef org::bluez::Device1 BluezDevice; typedef org::freedesktop::DBus::Properties DBusProperties; class DevicePrivate : public QObject { Q_OBJECT public: explicit DevicePrivate(const QString &path, const QVariantMap &properties, const AdapterPtr &adapter); void init(const QVariantMap &properties); void interfacesAdded(const QString &path, const QVariantMapMap &interfaces); void interfacesRemoved(const QString &path, const QStringList &interfaces); QDBusPendingReply<> setDBusProperty(const QString &name, const QVariant &value); void propertiesChanged(const QString &interface, const QVariantMap &changed, const QStringList &invalidated); void namePropertyChanged(const QString &value); void aliasPropertyChanged(const QString &value); void addressPropertyChanged(const QString &value); void classPropertyChanged(quint32 value); QWeakPointer q; BluezDevice *m_bluezDevice; DBusProperties *m_dbusProperties; QString m_address; QString m_name; QString m_alias; quint32 m_deviceClass; quint16 m_appearance; QString m_icon; bool m_paired; bool m_trusted; bool m_blocked; bool m_legacyPairing; qint16 m_rssi; bool m_connected; QStringList m_uuids; QString m_modalias; + BatteryPtr m_battery; InputPtr m_input; MediaPlayerPtr m_mediaPlayer; MediaTransportPtr m_mediaTransport; AdapterPtr m_adapter; }; } // namespace BluezQt #endif // BLUEZQT_DEVICE_P_H diff --git a/src/imports/CMakeLists.txt b/src/imports/CMakeLists.txt index 59668a5..299a5fd 100644 --- a/src/imports/CMakeLists.txt +++ b/src/imports/CMakeLists.txt @@ -1,25 +1,26 @@ set(bluezqtextensionplugin_SRCS declarativemanager.cpp declarativeadapter.cpp + declarativebattery.cpp declarativedevice.cpp declarativeinput.cpp declarativemediaplayer.cpp declarativedevicesmodel.cpp bluezqtextensionplugin.cpp ) # Needed to run QML autotests configure_file(qmldir org/kde/bluezqt/qmldir COPYONLY) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY org/kde/bluezqt) add_library(bluezqtextensionplugin SHARED ${bluezqtextensionplugin_SRCS}) target_link_libraries(bluezqtextensionplugin Qt5::Core Qt5::Qml KF5::BluezQt ) install(TARGETS bluezqtextensionplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/bluezqt) install(FILES DevicesModel.qml DESTINATION ${QML_INSTALL_DIR}/org/kde/bluezqt) install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/bluezqt) diff --git a/src/imports/bluezqtextensionplugin.cpp b/src/imports/bluezqtextensionplugin.cpp index 015da9a..1dca4f1 100644 --- a/src/imports/bluezqtextensionplugin.cpp +++ b/src/imports/bluezqtextensionplugin.cpp @@ -1,86 +1,88 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "bluezqtextensionplugin.h" #include "declarativemanager.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativedevice.h" #include "declarativeinput.h" #include "declarativemediaplayer.h" #include "declarativedevicesmodel.h" #include "device.h" #include "pendingcall.h" #include "services.h" #include // krazy:exclude=includes static QObject *manager_singleton(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) return new DeclarativeManager; } static QJSValue services_singleton(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) QJSValue object = scriptEngine->newObject(); object.setProperty(QStringLiteral("ServiceDiscoveryServer"), BluezQt::Services::ServiceDiscoveryServer); object.setProperty(QStringLiteral("SerialPort"), BluezQt::Services::SerialPort); object.setProperty(QStringLiteral("DialupNetworking"), BluezQt::Services::DialupNetworking); object.setProperty(QStringLiteral("ObexObjectPush"), BluezQt::Services::ObexObjectPush); object.setProperty(QStringLiteral("ObexFileTransfer"), BluezQt::Services::ObexFileTransfer); object.setProperty(QStringLiteral("Headset"), BluezQt::Services::Headset); object.setProperty(QStringLiteral("AudioSource"), BluezQt::Services::AudioSource); object.setProperty(QStringLiteral("AudioVideoRemoteControlTarget"), BluezQt::Services::AudioVideoRemoteControlTarget); object.setProperty(QStringLiteral("AdvancedAudioDistribution"), BluezQt::Services::AdvancedAudioDistribution); object.setProperty(QStringLiteral("AudioVideoRemoteControl"), BluezQt::Services::AudioVideoRemoteControl); object.setProperty(QStringLiteral("HeadsetAudioGateway"), BluezQt::Services::HeadsetAudioGateway); object.setProperty(QStringLiteral("Panu"), BluezQt::Services::Panu); object.setProperty(QStringLiteral("Nap"), BluezQt::Services::Nap); object.setProperty(QStringLiteral("Handsfree"), BluezQt::Services::Handsfree); object.setProperty(QStringLiteral("HandsfreeAudioGateway"), BluezQt::Services::HandsfreeAudioGateway); object.setProperty(QStringLiteral("HumanInterfaceDevice"), BluezQt::Services::HumanInterfaceDevice); object.setProperty(QStringLiteral("SimAccess"), BluezQt::Services::SimAccess); object.setProperty(QStringLiteral("PhonebookAccessServer"), BluezQt::Services::PhonebookAccessServer); object.setProperty(QStringLiteral("MessageAccessServer"), BluezQt::Services::MessageAccessServer); object.setProperty(QStringLiteral("PnpInformation"), BluezQt::Services::PnpInformation); return object; } void BluezQtExtensionPlugin::registerTypes(const char *uri) { using namespace BluezQt; Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.bluezqt")); qmlRegisterSingletonType(uri, 1, 0, "Manager", manager_singleton); qmlRegisterType(uri, 1, 0, "DevicesModelPrivate"); qmlRegisterUncreatableType(uri, 1, 0, "Adapter", QStringLiteral("Adapter cannot be created")); + qmlRegisterUncreatableType(uri, 1, 0, "Battery", QStringLiteral("Battery cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "Device", QStringLiteral("Device cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "Input", QStringLiteral("Input cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "MediaPlayer", QStringLiteral("MediaPlayer cannot be created")); qmlRegisterUncreatableType(uri, 1, 0, "PendingCall", QStringLiteral("PendingCall cannot be created")); qmlRegisterSingletonType(uri, 1, 0, "Services", services_singleton); } diff --git a/src/imports/declarativebattery.cpp b/src/imports/declarativebattery.cpp new file mode 100644 index 0000000..d70d4f5 --- /dev/null +++ b/src/imports/declarativebattery.cpp @@ -0,0 +1,35 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "declarativebattery.h" + +DeclarativeBattery::DeclarativeBattery(const BluezQt::BatteryPtr &battery, QObject *parent) + : QObject(parent) + , m_battery(battery) +{ + connect(m_battery.data(), &BluezQt::Battery::percentageChanged, this, &DeclarativeBattery::percentageChanged); +} + +int DeclarativeBattery::percentage() const +{ + return m_battery->percentage(); +} diff --git a/src/imports/declarativebattery.h b/src/imports/declarativebattery.h new file mode 100644 index 0000000..bce6193 --- /dev/null +++ b/src/imports/declarativebattery.h @@ -0,0 +1,45 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Kai Uwe Broulik + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 6 of version 3 of the license. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef DECLARATIVEBATTERY_H +#define DECLARATIVEBATTERY_H + +#include "battery.h" + +class DeclarativeBattery : public QObject +{ + Q_OBJECT + Q_PROPERTY(int percentage READ percentage NOTIFY percentageChanged) + +public: + explicit DeclarativeBattery(const BluezQt::BatteryPtr &battery, QObject *parent = nullptr); + + int percentage() const; + +Q_SIGNALS: + void percentageChanged(int percentage); + +private: + BluezQt::BatteryPtr m_battery; +}; + +#endif // DECLARATIVEBATTERY_H diff --git a/src/imports/declarativedevice.cpp b/src/imports/declarativedevice.cpp index c456565..1928350 100644 --- a/src/imports/declarativedevice.cpp +++ b/src/imports/declarativedevice.cpp @@ -1,238 +1,260 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "declarativedevice.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativeinput.h" #include "declarativemediaplayer.h" #include DeclarativeDevice::DeclarativeDevice(BluezQt::DevicePtr device, DeclarativeAdapter *adapter) : QObject(adapter) , m_device(device) , m_adapter(adapter) + , m_battery(nullptr) , m_input(nullptr) , m_mediaPlayer(nullptr) { connect(m_device.data(), &BluezQt::Device::nameChanged, this, &DeclarativeDevice::nameChanged); connect(m_device.data(), &BluezQt::Device::friendlyNameChanged, this, &DeclarativeDevice::friendlyNameChanged); connect(m_device.data(), &BluezQt::Device::remoteNameChanged, this, &DeclarativeDevice::remoteNameChanged); connect(m_device.data(), &BluezQt::Device::deviceClassChanged, this, &DeclarativeDevice::deviceClassChanged); connect(m_device.data(), &BluezQt::Device::typeChanged, this, &DeclarativeDevice::typeChanged); connect(m_device.data(), &BluezQt::Device::appearanceChanged, this, &DeclarativeDevice::appearanceChanged); connect(m_device.data(), &BluezQt::Device::iconChanged, this, &DeclarativeDevice::iconChanged); connect(m_device.data(), &BluezQt::Device::pairedChanged, this, &DeclarativeDevice::pairedChanged); connect(m_device.data(), &BluezQt::Device::trustedChanged, this, &DeclarativeDevice::trustedChanged); connect(m_device.data(), &BluezQt::Device::blockedChanged, this, &DeclarativeDevice::blockedChanged); connect(m_device.data(), &BluezQt::Device::legacyPairingChanged, this, &DeclarativeDevice::legacyPairingChanged); connect(m_device.data(), &BluezQt::Device::rssiChanged, this, &DeclarativeDevice::rssiChanged); connect(m_device.data(), &BluezQt::Device::connectedChanged, this, &DeclarativeDevice::connectedChanged); connect(m_device.data(), &BluezQt::Device::uuidsChanged, this, &DeclarativeDevice::uuidsChanged); connect(m_device.data(), &BluezQt::Device::modaliasChanged, this, &DeclarativeDevice::modaliasChanged); connect(m_device.data(), &BluezQt::Device::mediaPlayerChanged, this, &DeclarativeDevice::updateMediaPlayer); connect(m_device.data(), &BluezQt::Device::inputChanged, this, &DeclarativeDevice::updateInput); + connect(m_device.data(), &BluezQt::Device::batteryChanged, this, &DeclarativeDevice::updateBattery); connect(m_device.data(), &BluezQt::Device::deviceRemoved, this, [this]() { Q_EMIT deviceRemoved(this); }); connect(m_device.data(), &BluezQt::Device::deviceChanged, this, [this]() { Q_EMIT deviceChanged(this); }); updateInput(); updateMediaPlayer(); } QString DeclarativeDevice::ubi() const { return m_device->ubi(); } QString DeclarativeDevice::address() const { return m_device->address(); } QString DeclarativeDevice::name() const { return m_device->name(); } void DeclarativeDevice::setName(const QString &name) { m_device->setName(name); } QString DeclarativeDevice::friendlyName() const { return m_device->friendlyName(); } QString DeclarativeDevice::remoteName() const { return m_device->remoteName(); } quint32 DeclarativeDevice::deviceClass() const { return m_device->deviceClass(); } BluezQt::Device::Type DeclarativeDevice::type() const { return m_device->type(); } quint16 DeclarativeDevice::appearance() const { return m_device->appearance(); } QString DeclarativeDevice::icon() const { return m_device->icon(); } bool DeclarativeDevice::isPaired() const { return m_device->isPaired(); } bool DeclarativeDevice::isTrusted() const { return m_device->isTrusted(); } void DeclarativeDevice::setTrusted(bool trusted) { m_device->setTrusted(trusted); } bool DeclarativeDevice::isBlocked() const { return m_device->isBlocked(); } void DeclarativeDevice::setBlocked(bool blocked) { m_device->setBlocked(blocked); } bool DeclarativeDevice::hasLegacyPairing() const { return m_device->hasLegacyPairing(); } qint16 DeclarativeDevice::rssi() const { return m_device->rssi(); } bool DeclarativeDevice::isConnected() const { return m_device->isConnected(); } QStringList DeclarativeDevice::uuids() const { return m_device->uuids(); } QString DeclarativeDevice::modalias() const { return m_device->modalias(); } +DeclarativeBattery *DeclarativeDevice::battery() const +{ + return m_battery; +} + DeclarativeInput *DeclarativeDevice::input() const { return m_input; } DeclarativeMediaPlayer *DeclarativeDevice::mediaPlayer() const { return m_mediaPlayer; } DeclarativeAdapter *DeclarativeDevice::adapter() const { return m_adapter; } BluezQt::PendingCall *DeclarativeDevice::connectToDevice() { return m_device->connectToDevice(); } BluezQt::PendingCall *DeclarativeDevice::disconnectFromDevice() { return m_device->disconnectFromDevice(); } BluezQt::PendingCall *DeclarativeDevice::connectProfile(const QString &uuid) { return m_device->connectProfile(uuid); } BluezQt::PendingCall *DeclarativeDevice::disconnectProfile(const QString &uuid) { return m_device->disconnectProfile(uuid); } BluezQt::PendingCall *DeclarativeDevice::pair() { return m_device->pair(); } BluezQt::PendingCall *DeclarativeDevice::cancelPairing() { return m_device->cancelPairing(); } +void DeclarativeDevice::updateBattery() +{ + if (m_battery) { + m_battery->deleteLater(); + m_battery = nullptr; + } + + if (m_device->battery()) { + m_battery = new DeclarativeBattery(m_device->battery(), this); + } + + Q_EMIT batteryChanged(m_battery); +} + void DeclarativeDevice::updateInput() { if (m_input) { m_input->deleteLater(); m_input = nullptr; } if (m_device->input()) { m_input = new DeclarativeInput(m_device->input(), this); } Q_EMIT inputChanged(m_input); } void DeclarativeDevice::updateMediaPlayer() { if (m_mediaPlayer) { m_mediaPlayer->deleteLater(); m_mediaPlayer = nullptr; } if (m_device->mediaPlayer()) { m_mediaPlayer = new DeclarativeMediaPlayer(m_device->mediaPlayer(), this); } Q_EMIT mediaPlayerChanged(m_mediaPlayer); } diff --git a/src/imports/declarativedevice.h b/src/imports/declarativedevice.h index d6731b5..1f3c7ee 100644 --- a/src/imports/declarativedevice.h +++ b/src/imports/declarativedevice.h @@ -1,142 +1,148 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef DECLARATIVEDEVICE_H #define DECLARATIVEDEVICE_H #include "device.h" class DeclarativeAdapter; +class DeclarativeBattery; class DeclarativeInput; class DeclarativeMediaPlayer; class DeclarativeDevice : public QObject { Q_OBJECT Q_PROPERTY(QString ubi READ ubi CONSTANT) Q_PROPERTY(QString address READ address CONSTANT) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString friendlyName READ friendlyName NOTIFY friendlyNameChanged) Q_PROPERTY(QString remoteName READ remoteName NOTIFY remoteNameChanged) Q_PROPERTY(quint32 deviceClass READ deviceClass NOTIFY deviceClassChanged) Q_PROPERTY(BluezQt::Device::Type type READ type NOTIFY typeChanged) Q_PROPERTY(quint16 appearance READ appearance NOTIFY appearanceChanged) Q_PROPERTY(QString icon READ icon NOTIFY iconChanged) Q_PROPERTY(bool paired READ isPaired NOTIFY pairedChanged) Q_PROPERTY(bool trusted READ isTrusted WRITE setTrusted NOTIFY trustedChanged) Q_PROPERTY(bool blocked READ isBlocked WRITE setBlocked NOTIFY blockedChanged) Q_PROPERTY(bool legacyPairing READ hasLegacyPairing NOTIFY legacyPairingChanged) Q_PROPERTY(qint16 rssi READ rssi NOTIFY rssiChanged) Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged) Q_PROPERTY(QStringList uuids READ uuids NOTIFY uuidsChanged) Q_PROPERTY(QString modalias READ modalias NOTIFY modaliasChanged) Q_PROPERTY(DeclarativeInput* input READ input NOTIFY inputChanged) Q_PROPERTY(DeclarativeMediaPlayer* mediaPlayer READ mediaPlayer NOTIFY mediaPlayerChanged) Q_PROPERTY(DeclarativeAdapter* adapter READ adapter CONSTANT) public: explicit DeclarativeDevice(BluezQt::DevicePtr device, DeclarativeAdapter *adapter); QString ubi() const; QString address() const; QString name() const; void setName(const QString &name); QString friendlyName() const; QString remoteName() const; quint32 deviceClass() const; BluezQt::Device::Type type() const; quint16 appearance() const; QString icon() const; bool isPaired() const; bool isTrusted() const; void setTrusted(bool trusted); bool isBlocked() const; void setBlocked(bool blocked); bool hasLegacyPairing() const; qint16 rssi() const; bool isConnected() const; QStringList uuids() const; QString modalias() const; + DeclarativeBattery *battery() const; + DeclarativeInput *input() const; DeclarativeMediaPlayer *mediaPlayer() const; DeclarativeAdapter *adapter() const; public Q_SLOTS: BluezQt::PendingCall *connectToDevice(); BluezQt::PendingCall *disconnectFromDevice(); BluezQt::PendingCall *connectProfile(const QString &uuid); BluezQt::PendingCall *disconnectProfile(const QString &uuid); BluezQt::PendingCall *pair(); BluezQt::PendingCall *cancelPairing(); Q_SIGNALS: void deviceRemoved(DeclarativeDevice *device); void deviceChanged(DeclarativeDevice *device); void nameChanged(const QString &name); void friendlyNameChanged(const QString &friendlyName); void remoteNameChanged(const QString &remoteName); void deviceClassChanged(quint32 deviceClass); void typeChanged(BluezQt::Device::Type type); void appearanceChanged(quint16 appearance); void iconChanged(const QString &icon); void pairedChanged(bool paired); void trustedChanged(bool trusted); void blockedChanged(bool blocked); void legacyPairingChanged(bool legacyPairing); void rssiChanged(qint16 rssi); void connectedChanged(bool connected); void uuidsChanged(const QStringList &uuids); void modaliasChanged(const QString &modalias); + void batteryChanged(DeclarativeBattery *battery); void inputChanged(DeclarativeInput *input); void mediaPlayerChanged(DeclarativeMediaPlayer *mediaPlayer); private: + void updateBattery(); void updateInput(); void updateMediaPlayer(); BluezQt::DevicePtr m_device; DeclarativeAdapter *m_adapter; + DeclarativeBattery *m_battery; DeclarativeInput *m_input; DeclarativeMediaPlayer *m_mediaPlayer; }; #endif // DECLARATIVEDEVICE_H diff --git a/src/imports/declarativedevicesmodel.cpp b/src/imports/declarativedevicesmodel.cpp index eff2e2e..60eadd5 100644 --- a/src/imports/declarativedevicesmodel.cpp +++ b/src/imports/declarativedevicesmodel.cpp @@ -1,84 +1,90 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "declarativedevicesmodel.h" #include "declarativemanager.h" #include "declarativeadapter.h" +#include "declarativebattery.h" #include "declarativedevice.h" #include "declarativemediaplayer.h" DeclarativeDevicesModel::DeclarativeDevicesModel(QObject *parent) : QSortFilterProxyModel(parent) , m_manager(nullptr) , m_model(nullptr) { } DeclarativeManager *DeclarativeDevicesModel::manager() const { return m_manager; } void DeclarativeDevicesModel::setManager(DeclarativeManager *manager) { m_manager = manager; m_model = new BluezQt::DevicesModel(m_manager, this); setSourceModel(m_model); } QHash DeclarativeDevicesModel::roleNames() const { QHash roles = QSortFilterProxyModel::roleNames(); roles[DeviceRole] = QByteArrayLiteral("Device"); roles[AdapterRole] = QByteArrayLiteral("Adapter"); roles[MediaPlayerRole] = QByteArrayLiteral("MediaPlayer"); + roles[BatteryRole] = QByteArrayLiteral("Battery"); return roles; } QVariant DeclarativeDevicesModel::data(const QModelIndex &index, int role) const { if (!m_model) { return QSortFilterProxyModel::data(index, role); } BluezQt::DevicePtr dev = m_model->device(mapToSource(index)); if (!dev) { return QSortFilterProxyModel::data(index, role); } switch (role) { case DeviceRole: return QVariant::fromValue(m_manager->declarativeDeviceFromPtr(dev)); case AdapterRole: return QVariant::fromValue(m_manager->declarativeAdapterFromPtr(dev->adapter())); case MediaPlayerRole: if (DeclarativeDevice *device = m_manager->declarativeDeviceFromPtr(dev)) { return QVariant::fromValue(device->mediaPlayer()); } - // fallthrough - Q_FALLTHROUGH(); - default: - return QSortFilterProxyModel::data(index, role); + break; + case BatteryRole: + if (DeclarativeDevice *device = m_manager->declarativeDeviceFromPtr(dev)) { + return QVariant::fromValue(device->battery()); + } + break; } + + return QSortFilterProxyModel::data(index, role); } diff --git a/src/imports/declarativedevicesmodel.h b/src/imports/declarativedevicesmodel.h index 8d034b4..8ab5df4 100644 --- a/src/imports/declarativedevicesmodel.h +++ b/src/imports/declarativedevicesmodel.h @@ -1,58 +1,59 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef DECLARATIVEDEVICESMODEL_H #define DECLARATIVEDEVICESMODEL_H #include #include "devicesmodel.h" class DeclarativeManager; class DeclarativeDevicesModel : public QSortFilterProxyModel { Q_OBJECT Q_PROPERTY(DeclarativeManager* manager READ manager WRITE setManager) public: enum DeclarativeDeviceRoles { DeviceRole = BluezQt::DevicesModel::LastRole + 1, AdapterRole = BluezQt::DevicesModel::LastRole + 2, - MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3 + MediaPlayerRole = BluezQt::DevicesModel::LastRole + 3, + BatteryRole = BluezQt::DevicesModel::LastRole + 4 }; explicit DeclarativeDevicesModel(QObject *parent = nullptr); DeclarativeManager *manager() const; void setManager(DeclarativeManager *manager); QHash roleNames() const override; QVariant data(const QModelIndex &index, int role) const override; private: DeclarativeManager *m_manager; BluezQt::DevicesModel *m_model; }; #endif // DECLARATIVEMANAGER_H diff --git a/src/interfaces/org.bluez.Battery1.xml b/src/interfaces/org.bluez.Battery1.xml new file mode 100644 index 0000000..1fcbef8 --- /dev/null +++ b/src/interfaces/org.bluez.Battery1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/types.h b/src/types.h index 3238bf1..48bac0f 100644 --- a/src/types.h +++ b/src/types.h @@ -1,71 +1,73 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * * Copyright (C) 2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef BLUEZQT_TYPES_H #define BLUEZQT_TYPES_H #include namespace BluezQt { class Manager; class Adapter; +class Battery; class Device; class Input; class GattManager; class LEAdvertisingManager; class Media; class MediaPlayer; class MediaPlayerTrack; class MediaTransport; class Agent; class DevicesModel; class InitManagerJob; class Profile; class PendingCall; class ObexManager; class ObexSession; class ObexTransfer; class InitObexManagerJob; class ObexAgent; class ObexFileTransfer; class ObexFileTransferEntry; class ObexObjectPush; class GattApplication; typedef QSharedPointer ManagerPtr; typedef QSharedPointer AdapterPtr; +typedef QSharedPointer BatteryPtr; typedef QSharedPointer DevicePtr; typedef QSharedPointer InputPtr; typedef QSharedPointer GattManagerPtr; typedef QSharedPointer LEAdvertisingManagerPtr; typedef QSharedPointer MediaPtr; typedef QSharedPointer MediaPlayerPtr; typedef QSharedPointer MediaTransportPtr; typedef QSharedPointer ObexManagerPtr; typedef QSharedPointer ObexSessionPtr; typedef QSharedPointer ObexTransferPtr; } // namespace BluezQt #endif // BLUEZQT_TYPES_H diff --git a/src/utils.cpp b/src/utils.cpp index a9a64db..3768324 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,326 +1,333 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014-2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "utils.h" #include "manager.h" #include "obexmanager.h" #include "bluezqt_export.h" #include #include #include namespace BluezQt { class GlobalData { public: explicit GlobalData(); bool testRun; QString orgFreedesktopDBus; QString orgFreedesktopDBusProperties; QString orgBluez; QString orgBluezAdapter1; + QString orgBluezBattery1; QString orgBluezDevice1; QString orgBluezInput1; QString orgBluezGattManager1; QString orgBluezLEAdvertisingManager1; QString orgBluezMedia1; QString orgBluezMediaPlayer1; QString orgBluezMediaTransport1; QString orgBluezAgentManager1; QString orgBluezProfileManager1; QString orgBluezObex; QString orgBluezObexClient1; QString orgBluezObexAgentManager1; QString orgBluezObexSession1; QString orgBluezObexTransfer1; QPointer manager; QPointer obexManager; }; GlobalData::GlobalData() { testRun = false; orgFreedesktopDBus = QStringLiteral("org.freedesktop.DBus"); orgFreedesktopDBusProperties = QStringLiteral("org.freedesktop.DBus.Properties"); orgBluez = QStringLiteral("org.bluez"); orgBluezAdapter1 = QStringLiteral("org.bluez.Adapter1"); + orgBluezBattery1 = QStringLiteral("org.bluez.Battery1"); orgBluezDevice1 = QStringLiteral("org.bluez.Device1"); orgBluezInput1 = QStringLiteral("org.bluez.Input1"); orgBluezGattManager1 = QStringLiteral("org.bluez.GattManager1"); orgBluezLEAdvertisingManager1 = QStringLiteral("org.bluez.LEAdvertisingManager1"); orgBluezMedia1 = QStringLiteral("org.bluez.Media1"); orgBluezMediaPlayer1 = QStringLiteral("org.bluez.MediaPlayer1"); orgBluezMediaTransport1 = QStringLiteral("org.bluez.MediaTransport1"); orgBluezAgentManager1 = QStringLiteral("org.bluez.AgentManager1"); orgBluezProfileManager1 = QStringLiteral("org.bluez.ProfileManager1"); orgBluezObex = QStringLiteral("org.bluez.obex"); orgBluezObexClient1 = QStringLiteral("org.bluez.obex.Client1"); orgBluezObexAgentManager1 = QStringLiteral("org.bluez.obex.AgentManager1"); orgBluezObexSession1 = QStringLiteral("org.bluez.obex.Session1"); orgBluezObexTransfer1 = QStringLiteral("org.bluez.obex.Transfer1"); } Q_GLOBAL_STATIC(GlobalData, globalData) // For fakebluez tests BLUEZQT_EXPORT void bluezqt_initFakeBluezTestRun() { globalData->testRun = true; globalData->orgBluez = QStringLiteral("org.kde.bluezqt.fakebluez"); globalData->orgBluezObex = QStringLiteral("org.kde.bluezqt.fakebluez"); } QString Strings::orgFreedesktopDBus() { return globalData->orgFreedesktopDBus; } QString Strings::orgFreedesktopDBusProperties() { return globalData->orgFreedesktopDBusProperties; } QString Strings::orgBluez() { return globalData->orgBluez; } QString Strings::orgBluezAdapter1() { return globalData->orgBluezAdapter1; } +QString Strings::orgBluezBattery1() +{ + return globalData->orgBluezBattery1; +} + QString Strings::orgBluezDevice1() { return globalData->orgBluezDevice1; } QString Strings::orgBluezInput1() { return globalData->orgBluezInput1; } QString Strings::orgBluezGattManager1() { return globalData->orgBluezGattManager1; } QString Strings::orgBluezLEAdvertisingManager1() { return globalData->orgBluezLEAdvertisingManager1; } QString Strings::orgBluezMedia1() { return globalData->orgBluezMedia1; } QString Strings::orgBluezMediaPlayer1() { return globalData->orgBluezMediaPlayer1; } QString Strings::orgBluezMediaTransport1() { return globalData->orgBluezMediaTransport1; } QString Strings::orgBluezAgentManager1() { return globalData->orgBluezAgentManager1; } QString Strings::orgBluezProfileManager1() { return globalData->orgBluezProfileManager1; } QString Strings::orgBluezObex() { return globalData->orgBluezObex; } QString Strings::orgBluezObexClient1() { return globalData->orgBluezObexClient1; } QString Strings::orgBluezObexAgentManager1() { return globalData->orgBluezObexAgentManager1; } QString Strings::orgBluezObexSession1() { return globalData->orgBluezObexSession1; } QString Strings::orgBluezObexTransfer1() { return globalData->orgBluezObexTransfer1; } QDBusConnection DBusConnection::orgBluez() { if (globalData->testRun) { return QDBusConnection::sessionBus(); } return QDBusConnection::systemBus(); } QDBusConnection DBusConnection::orgBluezObex() { return QDBusConnection::sessionBus(); } Manager *Instance::manager() { return globalData->manager; } void Instance::setManager(Manager *manager) { globalData->manager = manager; } ObexManager *Instance::obexManager() { return globalData->obexManager; } void Instance::setObexManager(ObexManager *obexManager) { globalData->obexManager = obexManager; } QStringList stringListToUpper(const QStringList &list) { QStringList converted; converted.reserve(list.size()); for (const QString &str : list) { converted.append(str.toUpper()); } return converted; } Device::Type classToType(quint32 classNum) { switch ((classNum & 0x1f00) >> 8) { case 0x01: return Device::Computer; case 0x02: switch ((classNum & 0xfc) >> 2) { case 0x04: return Device::Modem; default: return Device::Phone; } case 0x03: return Device::Network; case 0x04: switch ((classNum & 0xfc) >> 2) { case 0x01: case 0x02: return Device::Headset; case 0x06: return Device::Headphones; default: return Device::AudioVideo; } case 0x05: switch ((classNum & 0xc0) >> 6) { case 0x00: switch ((classNum & 0x1e) >> 2) { case 0x01: case 0x02: return Device::Joypad; } break; case 0x01: return Device::Keyboard; case 0x02: switch ((classNum & 0x1e) >> 2) { case 0x05: return Device::Tablet; default: return Device::Mouse; } } return Device::Peripheral; case 0x06: if (classNum & 0x80) { return Device::Printer; } else if (classNum & 0x20) { return Device::Camera; } return Device::Imaging; case 0x07: return Device::Wearable; case 0x08: return Device::Toy; case 0x09: return Device::Health; default: return Device::Uncategorized; } } Device::Type appearanceToType(quint16 appearance) { switch ((appearance & 0xffc0) >> 6) { case 0x00: return Device::Uncategorized; case 0x01: // Generic Phone return Device::Phone; case 0x02: // Generic Computer return Device::Computer; case 0x05: // Generic Display return Device::AudioVideo; case 0x0a: // Generic Media Player return Device::AudioVideo; case 0x0b: // Generic Barcode Scanner return Device::Peripheral; case 0x0f: // Generic HID switch (appearance & 0x3f) { case 0x01: // Keyboard return Device::Keyboard; case 0x02: // Mouse return Device::Mouse; case 0x03: // Joystick case 0x04: // Gamepad return Device::Joypad; case 0x05: // Digitizer Tablet return Device::Tablet; case 0x08: // Barcode Scanner return Device::Peripheral; } // fall-through default: return Device::Uncategorized; } } } // namespace BluezQt diff --git a/src/utils.h b/src/utils.h index 2bfd8e4..94c1eed 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,84 +1,85 @@ /* * BluezQt - Asynchronous Bluez wrapper library * * Copyright (C) 2014-2015 David Rosca * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #ifndef BLUEZQT_UTILS_H #define BLUEZQT_UTILS_H #include "device.h" class QString; class QStringList; class QDBusConnection; namespace BluezQt { namespace Strings { QString orgFreedesktopDBus(); QString orgFreedesktopDBusProperties(); QString orgBluez(); QString orgBluezAdapter1(); +QString orgBluezBattery1(); QString orgBluezDevice1(); QString orgBluezInput1(); QString orgBluezGattManager1(); QString orgBluezLEAdvertisingManager1(); QString orgBluezMedia1(); QString orgBluezMediaPlayer1(); QString orgBluezMediaTransport1(); QString orgBluezAgentManager1(); QString orgBluezProfileManager1(); QString orgBluezObex(); QString orgBluezObexClient1(); QString orgBluezObexAgentManager1(); QString orgBluezObexSession1(); QString orgBluezObexTransfer1(); } namespace DBusConnection { QDBusConnection orgBluez(); QDBusConnection orgBluezObex(); } namespace Instance { Manager *manager(); void setManager(Manager *manager); ObexManager *obexManager(); void setObexManager(ObexManager *obexManager); } QStringList stringListToUpper(const QStringList &list); Device::Type classToType(quint32 classNum); Device::Type appearanceToType(quint16 appearance); } // namespace BluezQt #endif // BLUEZQT_UTILS_H