diff --git a/src/device.h b/src/device.h index 7650d6f..357ff33 100644 --- a/src/device.h +++ b/src/device.h @@ -1,518 +1,523 @@ /* * 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) + 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(InputPtr input READ input NOTIFY inputChanged) Q_PROPERTY(MediaPlayerPtr mediaPlayer READ mediaPlayer NOTIFY mediaPlayerChanged) 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 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 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 inititated 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 input have changed. */ void inputChanged(InputPtr input); /** * Indicates that device's media player have changed. */ void mediaPlayerChanged(MediaPlayerPtr mediaPlayer); 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 351162d..77158a0 100644 --- a/src/device_p.cpp +++ b/src/device_p.cpp @@ -1,225 +1,235 @@ /* * 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 "input.h" #include "input_p.h" #include "mediaplayer.h" #include "mediaplayer_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()) { m_input = InputPtr(new Input(path, it.value())); m_input->d->q = m_input.toWeakRef(); Q_EMIT q.data()->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.data()->mediaPlayerChanged(m_mediaPlayer); changed = true; } } if (changed) { Q_EMIT q.data()->deviceChanged(q.toStrongRef()); } } void DevicePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces) { Q_UNUSED(path) bool changed = false; Q_FOREACH (const QString &interface, interfaces) { if (interface == Strings::orgBluezInput1()) { m_input.clear(); Q_EMIT q.data()->inputChanged(m_input); changed = true; } else if (interface == Strings::orgBluezMediaPlayer1()) { m_mediaPlayer.clear(); Q_EMIT q.data()->mediaPlayerChanged(m_mediaPlayer); changed = true; } } if (changed) { Q_EMIT q.data()->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) { 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); } } Q_FOREACH (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.data()->deviceChanged(q.toStrongRef()); } void DevicePrivate::namePropertyChanged(const QString &value) { if (m_name != value) { m_name = value; Q_EMIT q.data()->remoteNameChanged(m_name); Q_EMIT q.data()->friendlyNameChanged(q.data()->friendlyName()); } } +void DevicePrivate::addressPropertyChanged(const QString &value) +{ + if (m_address != value) { + m_address = value; + Q_EMIT q.data()->addressChanged(m_address); + } +} + void DevicePrivate::aliasPropertyChanged(const QString &value) { if (m_alias != value) { m_alias = value; Q_EMIT q.data()->nameChanged(m_alias); Q_EMIT q.data()->friendlyNameChanged(q.data()->friendlyName()); } } void DevicePrivate::classPropertyChanged(quint32 value) { if (m_deviceClass != value) { m_deviceClass = value; Q_EMIT q.data()->deviceClassChanged(m_deviceClass); Q_EMIT q.data()->typeChanged(q.data()->type()); } } } // namespace BluezQt diff --git a/src/device_p.h b/src/device_p.h index f2a7bd2..c6eb3b6 100644 --- a/src/device_p.h +++ b/src/device_p.h @@ -1,83 +1,84 @@ /* * 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; InputPtr m_input; MediaPlayerPtr m_mediaPlayer; AdapterPtr m_adapter; }; } // namespace BluezQt #endif // BLUEZQT_DEVICE_P_H