/* * Copyright (C) 2017 Konsulko Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "dbus.h" DbusService::DbusService(QObject *parent) : QObject(parent) { } /* * Bluetooth */ void DbusService::setBluezPath(const QString& path) { this->bluezPath = path; } QString DbusService::getBluezPath() const { return this->bluezPath; } bool DbusService::enableBluetooth() { QDBusConnection system_bus = QDBusConnection::systemBus(); QString interface = "org.freedesktop.DBus.ObjectManager"; bool ret; if (!system_bus.isConnected()) return false; if (deviceConnected(system_bus)) initialBluetoothData(system_bus); ret = system_bus.connect(QString("org.bluez"), QString("/"), interface, "InterfacesAdded", this, SLOT(newBluetoothDevice(QDBusObjectPath,QVariantMap))); if (!ret) return false; ret = system_bus.connect(QString("org.bluez"), QString("/"), interface, "InterfacesRemoved", this, SLOT(removeBluetoothDevice(QDBusObjectPath,QStringList))); /* * Unregister InterfacesAdded on error condition */ if (!ret) system_bus.disconnect(QString("org.bluez"), QString("/"), interface, "InterfacesAdded", this, SLOT(newBluetoothDevice(QString,QVariantMap))); return ret; } bool DbusService::checkIfPlayer(const QString& path) const { QRegExp regex("^.*/player\\d$"); if (regex.exactMatch(path)) return true; return false; } bool DbusService::deviceConnected(const QDBusConnection& system_bus) { QDBusInterface interface("org.bluez", "/", "org.freedesktop.DBus.ObjectManager", system_bus); QDBusMessage result = interface.call("GetManagedObjects"); const QDBusArgument argument = result.arguments().at(0).value(); bool ret = false; if (argument.currentType() != QDBusArgument::MapType) return false; argument.beginMap(); while (!argument.atEnd()) { QString key; argument.beginMapEntry(); argument >> key; argument.endMapEntry(); ret = checkIfPlayer(key); if (ret) { newBluetoothDevice(QDBusObjectPath(key), QVariantMap()); break; } } argument.endMap(); return ret; } void DbusService::initialBluetoothData(const QDBusConnection& system_bus) { QDBusInterface interface("org.bluez", getBluezPath(), "org.freedesktop.DBus.Properties", system_bus); QDBusMessage result = interface.call("GetAll", "org.bluez.MediaPlayer1"); const QDBusArgument argument = result.arguments().at(0).value(); QString status, artist, title; int position = 0, duration = 0; if (argument.currentType() != QDBusArgument::MapType) return; argument.beginMap(); while (!argument.atEnd()) { QString key; QVariant value; argument.beginMapEntry(); argument >> key >> value; if (key == "Position") { position = value.toInt(); } else if (key == "Status") { status = value.toString(); } else if (key == "Track") { const QDBusArgument argument1 = qvariant_cast(value); QString key1; QVariant value1; argument1.beginMap(); while (!argument1.atEnd()) { argument1.beginMapEntry(); argument1 >> key1 >> value1; if (key1 == "Artist") artist = value1.toString(); else if (key1 == "Title") title = value1.toString(); else if (key1 == "Duration") duration = value1.toInt(); argument1.endMapEntry(); } argument1.endMap(); } argument.endMapEntry(); } argument.endMap(); emit processPlaylistHide(); emit displayBluetoothMetadata(artist, title, duration); emit updatePlayerStatus(status); emit updatePosition(position); } void DbusService::newBluetoothDevice(const QDBusObjectPath& item, const QVariantMap&) { QString path = item.path(); if (!checkIfPlayer(path)) return; if (!getBluezPath().isEmpty()) { qWarning() << "Another Bluetooth Player already connected"; return; } emit processPlaylistHide(); QDBusConnection system_bus = QDBusConnection::systemBus(); system_bus.connect(QString("org.bluez"), path, "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(processBluetoothEvent(QString,QVariantMap,QStringList))); setBluezPath(path); } void DbusService::removeBluetoothDevice(const QDBusObjectPath& item, const QStringList&) { QString path = item.path(); if (!checkIfPlayer(path)) return; if (getBluezPath().isEmpty()) { qWarning() << "No Bluetooth Player connected"; return; } QDBusConnection system_bus = QDBusConnection::systemBus(); system_bus.disconnect(QString("org.bluez"), path, "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(processBluetoothEvent(QString,QVariantMap,QStringList))); setBluezPath(QString()); emit processPlaylistShow(); } void DbusService::processBluetoothEvent(const QString&, const QVariantMap& map, const QStringList&) { if (map.contains("Track")) { QVariantMap track; map["Track"].value() >> track; emit displayBluetoothMetadata(track["Artist"].toString(), track["Title"].toString(), track["Duration"].toInt()); } if (map.contains("Position")) emit updatePosition(map["Position"].toInt()); if (map.contains("Status")) emit updatePlayerStatus(map["Status"].toString()); } void DbusService::processQMLEvent(const QString& state) { QDBusInterface interface("org.bluez", getBluezPath(), "org.bluez.MediaPlayer1", QDBusConnection::systemBus()); interface.call(state); } long DbusService::getCurrentPosition() { QDBusInterface interface("org.bluez", getBluezPath(), "org.bluez.MediaPlayer1", QDBusConnection::systemBus()); return interface.property("Position").toInt(); }