|
| 1 | +#include "adapter.hpp" |
| 2 | + |
| 3 | +#include <qcontainerfwd.h> |
| 4 | +#include <qdbusconnection.h> |
| 5 | +#include <qdbusextratypes.h> |
| 6 | +#include <qdbuspendingcall.h> |
| 7 | +#include <qdbuspendingreply.h> |
| 8 | +#include <qdebug.h> |
| 9 | +#include <qlogging.h> |
| 10 | +#include <qloggingcategory.h> |
| 11 | +#include <qstring.h> |
| 12 | +#include <qstringliteral.h> |
| 13 | +#include <qtypes.h> |
| 14 | + |
| 15 | +#include "../dbus/properties.hpp" |
| 16 | +#include "dbus_adapter.h" |
| 17 | + |
| 18 | +namespace qs::bluetooth { |
| 19 | + |
| 20 | +namespace { |
| 21 | +Q_LOGGING_CATEGORY(logAdapter, "quickshell.bluetooth.adapter", QtWarningMsg); |
| 22 | +} |
| 23 | + |
| 24 | +QString BluetoothAdapterState::toString(BluetoothAdapterState::Enum state) { |
| 25 | + switch (state) { |
| 26 | + case BluetoothAdapterState::Disabled: return QStringLiteral("Disabled"); |
| 27 | + case BluetoothAdapterState::Enabled: return QStringLiteral("Enabled"); |
| 28 | + case BluetoothAdapterState::Enabling: return QStringLiteral("Enabling"); |
| 29 | + case BluetoothAdapterState::Disabling: return QStringLiteral("Disabling"); |
| 30 | + case BluetoothAdapterState::Blocked: return QStringLiteral("Blocked"); |
| 31 | + default: return QStringLiteral("Unknown"); |
| 32 | + } |
| 33 | +} |
| 34 | + |
| 35 | +BluetoothAdapter::BluetoothAdapter(const QString& path, QObject* parent): QObject(parent) { |
| 36 | + this->mInterface = |
| 37 | + new DBusBluezAdapterInterface("org.bluez", path, QDBusConnection::systemBus(), this); |
| 38 | + |
| 39 | + if (!this->mInterface->isValid()) { |
| 40 | + qCWarning(logAdapter) << "Could not create DBus interface for adapter at" << path; |
| 41 | + this->mInterface = nullptr; |
| 42 | + return; |
| 43 | + } |
| 44 | + |
| 45 | + this->properties.setInterface(this->mInterface); |
| 46 | +} |
| 47 | + |
| 48 | +QString BluetoothAdapter::adapterId() const { |
| 49 | + auto path = this->path(); |
| 50 | + return path.sliced(path.lastIndexOf('/') + 1); |
| 51 | +} |
| 52 | + |
| 53 | +void BluetoothAdapter::setEnabled(bool enabled) { |
| 54 | + if (enabled == this->bEnabled) return; |
| 55 | + this->bEnabled = enabled; |
| 56 | + this->pEnabled.write(); |
| 57 | +} |
| 58 | + |
| 59 | +void BluetoothAdapter::setDiscoverable(bool discoverable) { |
| 60 | + if (discoverable == this->bDiscoverable) return; |
| 61 | + this->bDiscoverable = discoverable; |
| 62 | + this->pDiscoverable.write(); |
| 63 | +} |
| 64 | + |
| 65 | +void BluetoothAdapter::setDiscovering(bool discovering) { |
| 66 | + if (discovering) { |
| 67 | + this->startDiscovery(); |
| 68 | + } else { |
| 69 | + this->stopDiscovery(); |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +void BluetoothAdapter::setDiscoverableTimeout(quint32 timeout) { |
| 74 | + if (timeout == this->bDiscoverableTimeout) return; |
| 75 | + this->bDiscoverableTimeout = timeout; |
| 76 | + this->pDiscoverableTimeout.write(); |
| 77 | +} |
| 78 | + |
| 79 | +void BluetoothAdapter::setPairable(bool pairable) { |
| 80 | + if (pairable == this->bPairable) return; |
| 81 | + this->bPairable = pairable; |
| 82 | + this->pPairable.write(); |
| 83 | +} |
| 84 | + |
| 85 | +void BluetoothAdapter::setPairableTimeout(quint32 timeout) { |
| 86 | + if (timeout == this->bPairableTimeout) return; |
| 87 | + this->bPairableTimeout = timeout; |
| 88 | + this->pPairableTimeout.write(); |
| 89 | +} |
| 90 | + |
| 91 | +void BluetoothAdapter::addInterface(const QString& interface, const QVariantMap& properties) { |
| 92 | + if (interface == "org.bluez.Adapter1") { |
| 93 | + this->properties.updatePropertySet(properties, false); |
| 94 | + qCDebug(logAdapter) << "Updated Adapter properties for" << this; |
| 95 | + } |
| 96 | +} |
| 97 | + |
| 98 | +void BluetoothAdapter::removeDevice(const QString& devicePath) { |
| 99 | + qCDebug(logAdapter) << "Removing device" << devicePath << "from adapter" << this; |
| 100 | + |
| 101 | + auto reply = this->mInterface->RemoveDevice(QDBusObjectPath(devicePath)); |
| 102 | + |
| 103 | + auto* watcher = new QDBusPendingCallWatcher(reply, this); |
| 104 | + |
| 105 | + QObject::connect( |
| 106 | + watcher, |
| 107 | + &QDBusPendingCallWatcher::finished, |
| 108 | + this, |
| 109 | + [this, devicePath](QDBusPendingCallWatcher* watcher) { |
| 110 | + const QDBusPendingReply<> reply = *watcher; |
| 111 | + |
| 112 | + if (reply.isError()) { |
| 113 | + qCWarning(logAdapter).nospace() |
| 114 | + << "Failed to remove device " << devicePath << " from adapter" << this << ": " |
| 115 | + << reply.error().message(); |
| 116 | + } else { |
| 117 | + qCDebug(logAdapter) << "Successfully removed device" << devicePath << "from adapter" |
| 118 | + << this; |
| 119 | + } |
| 120 | + |
| 121 | + delete watcher; |
| 122 | + } |
| 123 | + ); |
| 124 | +} |
| 125 | + |
| 126 | +void BluetoothAdapter::startDiscovery() { |
| 127 | + if (this->bDiscovering) return; |
| 128 | + qCDebug(logAdapter) << "Starting discovery for adapter" << this; |
| 129 | + |
| 130 | + auto reply = this->mInterface->StartDiscovery(); |
| 131 | + auto* watcher = new QDBusPendingCallWatcher(reply, this); |
| 132 | + |
| 133 | + QObject::connect( |
| 134 | + watcher, |
| 135 | + &QDBusPendingCallWatcher::finished, |
| 136 | + this, |
| 137 | + [this](QDBusPendingCallWatcher* watcher) { |
| 138 | + const QDBusPendingReply<> reply = *watcher; |
| 139 | + |
| 140 | + if (reply.isError()) { |
| 141 | + qCWarning(logAdapter).nospace() |
| 142 | + << "Failed to start discovery on adapter" << this << ": " << reply.error().message(); |
| 143 | + } else { |
| 144 | + qCDebug(logAdapter) << "Successfully started discovery on adapter" << this; |
| 145 | + } |
| 146 | + |
| 147 | + delete watcher; |
| 148 | + } |
| 149 | + ); |
| 150 | +} |
| 151 | + |
| 152 | +void BluetoothAdapter::stopDiscovery() { |
| 153 | + if (!this->bDiscovering) return; |
| 154 | + qCDebug(logAdapter) << "Stopping discovery for adapter" << this; |
| 155 | + |
| 156 | + auto reply = this->mInterface->StopDiscovery(); |
| 157 | + auto* watcher = new QDBusPendingCallWatcher(reply, this); |
| 158 | + |
| 159 | + QObject::connect( |
| 160 | + watcher, |
| 161 | + &QDBusPendingCallWatcher::finished, |
| 162 | + this, |
| 163 | + [this](QDBusPendingCallWatcher* watcher) { |
| 164 | + const QDBusPendingReply<> reply = *watcher; |
| 165 | + |
| 166 | + if (reply.isError()) { |
| 167 | + qCWarning(logAdapter).nospace() |
| 168 | + << "Failed to stop discovery on adapter " << this << ": " << reply.error().message(); |
| 169 | + } else { |
| 170 | + qCDebug(logAdapter) << "Successfully stopped discovery on adapter" << this; |
| 171 | + } |
| 172 | + |
| 173 | + delete watcher; |
| 174 | + } |
| 175 | + ); |
| 176 | +} |
| 177 | + |
| 178 | +} // namespace qs::bluetooth |
| 179 | + |
| 180 | +namespace qs::dbus { |
| 181 | + |
| 182 | +using namespace qs::bluetooth; |
| 183 | + |
| 184 | +DBusResult<BluetoothAdapterState::Enum> |
| 185 | +DBusDataTransform<BluetoothAdapterState::Enum>::fromWire(const Wire& wire) { |
| 186 | + if (wire == QStringLiteral("off")) { |
| 187 | + return BluetoothAdapterState::Disabled; |
| 188 | + } else if (wire == QStringLiteral("on")) { |
| 189 | + return BluetoothAdapterState::Enabled; |
| 190 | + } else if (wire == QStringLiteral("off-enabling")) { |
| 191 | + return BluetoothAdapterState::Enabling; |
| 192 | + } else if (wire == QStringLiteral("on-disabling")) { |
| 193 | + return BluetoothAdapterState::Disabling; |
| 194 | + } else if (wire == QStringLiteral("off-blocked")) { |
| 195 | + return BluetoothAdapterState::Blocked; |
| 196 | + } else { |
| 197 | + return QDBusError( |
| 198 | + QDBusError::InvalidArgs, |
| 199 | + QString("Invalid BluetoothAdapterState: %1").arg(wire) |
| 200 | + ); |
| 201 | + } |
| 202 | +} |
| 203 | + |
| 204 | +} // namespace qs::dbus |
| 205 | + |
| 206 | +QDebug operator<<(QDebug debug, const qs::bluetooth::BluetoothAdapter* adapter) { |
| 207 | + auto saver = QDebugStateSaver(debug); |
| 208 | + |
| 209 | + if (adapter) { |
| 210 | + debug.nospace() << "BluetoothAdapter(" << static_cast<const void*>(adapter) |
| 211 | + << ", path=" << adapter->path() << ")"; |
| 212 | + } else { |
| 213 | + debug << "BluetoothAdapter(nullptr)"; |
| 214 | + } |
| 215 | + |
| 216 | + return debug; |
| 217 | +} |
0 commit comments