diff --git a/debian/guh-plugins.install b/debian/guh-plugins.install index 5262a585..8678448c 100644 --- a/debian/guh-plugins.install +++ b/debian/guh-plugins.install @@ -19,3 +19,5 @@ usr/lib/guh/plugins/libguh_devicepluginkodi.so usr/lib/guh/plugins/libguh_devicepluginelgato.so usr/lib/guh/plugins/libguh_devicepluginawattar.so usr/lib/guh/plugins/libguh_devicepluginnetatmo.so +usr/lib/guh/plugins/libguh_deviceplugindenon.so + diff --git a/plugins/deviceplugins/denon/denon.cpp b/plugins/deviceplugins/denon/denon.cpp new file mode 100644 index 00000000..2001842b --- /dev/null +++ b/plugins/deviceplugins/denon/denon.cpp @@ -0,0 +1,194 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2016 Bernhard Trinnes * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +d +#include "denon.h" + +Kodi::Kodi(const QHostAddress &hostAddress, const int &port, QObject *parent) : + QObject(parent), + m_muted(false), + m_volume(-1) +{ + m_connection = new KodiConnection(hostAddress, port, this); + connect (m_connection, &KodiConnection::connectionStatusChanged, this, &Kodi::connectionStatusChanged); + + m_jsonHandler = new KodiJsonHandler(m_connection, this); + connect(m_jsonHandler, &KodiJsonHandler::volumeChanged, this, &Kodi::onVolumeChanged); + connect(m_jsonHandler, &KodiJsonHandler::actionExecuted, this, &Kodi::actionExecuted); + connect(m_jsonHandler, &KodiJsonHandler::versionDataReceived, this, &Kodi::versionDataReceived); + connect(m_jsonHandler, &KodiJsonHandler::updateDataReceived, this, &Kodi::updateDataReceived); + connect(m_jsonHandler, &KodiJsonHandler::updateDataReceived, this, &Kodi::onUpdateFinished); + connect(m_jsonHandler, &KodiJsonHandler::onPlayerPlay, this, &Kodi::onPlayerPlay); + connect(m_jsonHandler, &KodiJsonHandler::onPlayerPause, this, &Kodi::onPlayerPause); + connect(m_jsonHandler, &KodiJsonHandler::onPlayerStop, this, &Kodi::onPlayerStop); +} + +QHostAddress Kodi::hostAddress() const +{ + return m_connection->hostAddress(); +} + +int Kodi::port() const +{ + return m_connection->port(); +} + +bool Kodi::connected() const +{ + return m_connection->connected(); +} + +void Kodi::setMuted(const bool &muted, const ActionId &actionId) +{ + QVariantMap params; + params.insert("mute", muted); + + m_jsonHandler->sendData("Application.SetMute", params, actionId); +} + +bool Kodi::muted() const +{ + return m_muted; +} + +void Kodi::setVolume(const int &volume, const ActionId &actionId) +{ + QVariantMap params; + params.insert("volume", volume); + + m_jsonHandler->sendData("Application.SetVolume", params, actionId); +} + +int Kodi::volume() const +{ + return m_volume; +} + +void Kodi::showNotification(const QString &message, const int &displayTime, const QString ¬ificationType, const ActionId &actionId) +{ + QVariantMap params; + params.insert("title", "guh notification"); + params.insert("message", message); + params.insert("displaytime", displayTime); + params.insert("image", notificationType); + + m_jsonHandler->sendData("GUI.ShowNotification", params, actionId); +} + +void Kodi::pressButton(const QString &button, const ActionId &actionId) +{ + QVariantMap params; + params.insert("action", button); + m_jsonHandler->sendData("Input.ExecuteAction", params, actionId); +} + +void Kodi::systemCommand(const QString &command, const ActionId &actionId) +{ + QString method; + if (command == "hibernate") { + method = "Hibernate"; + } else if (command == "reboot") { + method = "Reboot"; + } else if (command == "shutdown") { + method = "Shutdown"; + } else if (command == "suspend") { + method = "Suspend"; + } else { + // already checkt with allowed values + } + + m_jsonHandler->sendData("System." + method, QVariantMap(), actionId); +} + +void Kodi::videoLibrary(const QString &command, const ActionId &actionId) +{ + QString method; + if (command == "scan") { + method = "Scan"; + } else if (command == "clean") { + method = "Clean"; + } else { + // already checkt with allowed values + } + + m_jsonHandler->sendData("VideoLibrary." + method, QVariantMap(), actionId); +} + +void Kodi::audioLibrary(const QString &command, const ActionId &actionId) +{ + QString method; + if (command == "scan") { + method = "Scan"; + } else if (command == "clean") { + method = "Clean"; + } else { + // already checkt with allowed values + } + + m_jsonHandler->sendData("AudioLibrary." + method, QVariantMap(), actionId); +} + +void Kodi::update() +{ + QVariantMap params; + QVariantList properties; + properties.append("volume"); + properties.append("muted"); + properties.append("name"); + properties.append("version"); + params.insert("properties", properties); + + m_jsonHandler->sendData("Application.GetProperties", params, ActionId()); +} + +void Kodi::checkVersion() +{ + m_jsonHandler->sendData("JSONRPC.Version", QVariantMap(), ActionId()); +} + +void Kodi::connectKodi() +{ + m_connection->connectKodi(); +} + +void Kodi::disconnectKodi() +{ + m_connection->disconnectKodi(); +} + +void Kodi::onVolumeChanged(const int &volume, const bool &muted) +{ + if (m_volume != volume || m_muted != muted) { + m_volume = volume; + m_muted = muted; + emit stateChanged(); + } +} + +void Kodi::onUpdateFinished(const QVariantMap &data) +{ + if (data.contains("volume")) { + m_volume = data.value("volume").toInt(); + } + if (data.contains("muted")) { + m_muted = data.value("muted").toBool(); + } + emit stateChanged(); +} diff --git a/plugins/deviceplugins/denon/denon.h b/plugins/deviceplugins/denon/denon.h new file mode 100644 index 00000000..aa83e739 --- /dev/null +++ b/plugins/deviceplugins/denon/denon.h @@ -0,0 +1,86 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2015 Bernhard Trinnes * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DENON_H +#define DENON_H + +#include +#include + +#include "denonconnection.h" + +class Denon : public QObject +{ + Q_OBJECT +public: + + explicit Denon(const QHostAddress &hostAddress, const int &port = 9090, QObject *parent = 0); + + QHostAddress hostAddress() const; + int port() const; + + bool connected() const; + + // propertys + void setMuted(const bool &muted, const ActionId &actionId); + bool muted() const; + + void setVolume(const int &volume, const ActionId &actionId); + int volume() const; + + // actions + void showNotification(const QString &message, const int &displayTime, const QString ¬ificationType, const ActionId &actionId); + void pressButton(const QString &button, const ActionId &actionId); + void systemCommand(const QString &command, const ActionId &actionId); + void videoLibrary(const QString &command, const ActionId &actionId); + void audioLibrary(const QString &command, const ActionId &actionId); + + void update(); + void checkVersion(); + + void connectKodi(); + void disconnectKodi(); + +private: + DenonConnection *m_connection; + bool m_muted; + int m_volume; + +signals: + void connectionStatusChanged(); + void stateChanged(); + void actionExecuted(const ActionId &actionId, const bool &success); + void updateDataReceived(const QVariantMap &data); + void versionDataReceived(const QVariantMap &data); + + void onPlayerPlay(); + void onPlayerPause(); + void onPlayerStop(); + +private slots: + void onVolumeChanged(const int &volume, const bool &muted); + void onUpdateFinished(const QVariantMap &data); + + +}; + +#endif // DENON_H diff --git a/plugins/deviceplugins/denon/denon.pro b/plugins/deviceplugins/denon/denon.pro new file mode 100644 index 00000000..80f9bc87 --- /dev/null +++ b/plugins/deviceplugins/denon/denon.pro @@ -0,0 +1,11 @@ +include(../../plugins.pri) + +TARGET = $$qtLibraryTarget(guh_deviceplugindenon) + +SOURCES += \ + deviceplugindenon.cpp \ + denonconnection.cpp + +HEADERS += \ + deviceplugindenon.h \ + denonconnection.h diff --git a/plugins/deviceplugins/denon/denonconnection.cpp b/plugins/deviceplugins/denon/denonconnection.cpp new file mode 100644 index 00000000..7effd95d --- /dev/null +++ b/plugins/deviceplugins/denon/denonconnection.cpp @@ -0,0 +1,120 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2016 Bernhard Trinnes . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "denonconnection.h" +#include "extern-plugininfo.h" + +DenonConnection::DenonConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) : + QObject(parent), + m_hostAddress(hostAddress), + m_port(port), + m_connected(false) +{ + m_socket = new QTcpSocket(this); + + connect(m_socket, &QTcpSocket::connected, this, &DenonConnection::onConnected); + connect(m_socket, &QTcpSocket::disconnected, this, &DenonConnection::onDisconnected); + connect(m_socket, &QTcpSocket::readyRead, this, &DenonConnection::readData); + // Note: error signal will be interpreted as function, not as signal in C++11 + connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError))); +} + +DenonConnection::~DenonConnection() +{ + m_socket->close(); +} + +void DenonConnection::connectDenon() +{ + if (m_socket->state() == QAbstractSocket::ConnectingState) { + return; + } + m_socket->connectToHost(m_hostAddress, m_port); +} + +void DenonConnection::disconnectDenon() +{ + m_socket->close(); +} + +QHostAddress DenonConnection::hostAddress() const +{ + return m_hostAddress; +} + +int DenonConnection::port() const +{ + return m_port; +} + +bool DenonConnection::connected() +{ + return m_connected; +} + +void DenonConnection::sendData(const QByteArray &message) +{ + m_socket->write(message); +} + +void DenonConnection::onConnected() +{ + qCDebug(dcDenon) << "connected successfully to" << hostAddress().toString() << port(); + setConnected(true); +} + +void DenonConnection::onDisconnected() +{ + qCDebug(dcDenon) << "disconnected from" << hostAddress().toString() << port(); + setConnected(false); +} + +void DenonConnection::onError(QAbstractSocket::SocketError socketError) +{ + qCWarning(dcDenon) << "socket error:" << socketError << m_socket->errorString(); + emit socketErrorOccured(socketError); +} + +void DenonConnection::readData() +{ + QByteArray data = m_socket->readAll(); + + QStringList commandList = QString(data).split("}{"); + for(int i = 0; i < commandList.count(); ++i) { + QString command = commandList.at(i); + if(command.isEmpty()) { + continue; + } + if(i < commandList.count() - 1) { + command.append("}"); + } + if(i > 0) { + command.prepend("{"); + } + emit dataReady(command.toUtf8()); + } +} + +void DenonConnection::setConnected(const bool &connected) +{ + m_connected = connected; + emit connectionStatusChanged(); +} diff --git a/plugins/deviceplugins/denon/denonconnection.h b/plugins/deviceplugins/denon/denonconnection.h new file mode 100644 index 00000000..edd79418 --- /dev/null +++ b/plugins/deviceplugins/denon/denonconnection.h @@ -0,0 +1,68 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2016 Bernhard Trinnes * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DENONCONNECTION_H +#define DENONCONNECTION_H + +#include +#include +#include + +class DenonConnection : public QObject +{ + Q_OBJECT +public: + explicit DenonConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = 0); + ~DenonConnection(); + + void connectDenon(); + void disconnectDenon(); + + QHostAddress hostAddress() const; + int port() const; + + bool connected(); + + void sendData(const QByteArray &message); + +private: + QTcpSocket *m_socket; + + QHostAddress m_hostAddress; + int m_port; + bool m_connected; + +private slots: + void onConnected(); + void onDisconnected(); + void onError(QAbstractSocket::SocketError socketError); + void readData(); + + void setConnected(const bool &connected); + +signals: + void socketErrorOccured(QAbstractSocket::SocketError socketError); + void connectionStatusChanged(); + void dataReady(const QByteArray &data); + +}; + +#endif // DENONCONNECTION_H diff --git a/plugins/deviceplugins/denon/deviceplugindenon.cpp b/plugins/deviceplugins/denon/deviceplugindenon.cpp new file mode 100644 index 00000000..8a1fb982 --- /dev/null +++ b/plugins/deviceplugins/denon/deviceplugindenon.cpp @@ -0,0 +1,268 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2016 Bernhard Trinnes * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*! + \page denon.html + \title Denon + \brief Plugin for Denon AV + + \ingroup plugins + \ingroup guh-plugins + + This plug-in supports the + \l {http://www.denon.de/de/product/hometheater/avreceivers/avrx1000}{Denon AV Amplifier AVR-X1000} + + \chapter Plugin properties + Following JSON file contains the definition and the description of all available \l{DeviceClass}{DeviceClasses} + and \l{Vendor}{Vendors} of this \l{DevicePlugin}. + + For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}. + + \quotefile plugins/deviceplugins/denon/deviceplugindenon.json +*/ + + + +#include "deviceplugindenon.h" +#include "plugininfo.h" + +DevicePluginDenon::DevicePluginDenon() +{ + +} + +DeviceManager::HardwareResources DevicePluginDenon::requiredHardware() const +{ + return DeviceManager::HardwareResourceTimer; +} + +DeviceManager::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) +{ + qCDebug(dcDenon) << "Setup Denon device" << device->paramValue("ip").toString(); + + // Check if we already have a denon device + if (!myDevices().isEmpty()) { + qCWarning(dcDenon()) << "Could not add denon device. Only one denon device allowed."; + return DeviceManager::DeviceSetupStatusFailure; + } + + QHostAddress address(device->paramValue("ip").toString()); + if (address.isNull()) { + qCWarning(dcDenon()) << "Could not parse ip address" << device->paramValue("ip").toString(); + return DeviceManager::DeviceSetupStatusFailure; + } + + m_device = device; + m_denonConnection = new DenonConnection(address, 23, this); + connect(m_denonConnection.data(), &DenonConnection::connectionStatusChanged, this, &DevicePluginDenon::onConnectionChanged); + connect(m_denonConnection.data(), &DenonConnection::socketErrorOccured, this, &DevicePluginDenon::onSocketError); + connect(m_denonConnection.data(), &DenonConnection::dataReady, this, &DevicePluginDenon::onDataReceived); + + m_asyncSetups.append(m_denonConnection); + m_denonConnection->connectDenon(); + + return DeviceManager::DeviceSetupStatusAsync; +} + +void DevicePluginDenon::deviceRemoved(Device *device) +{ + qCDebug(dcDenon) << "Delete " << device->name(); + if (m_denonConnection.isNull()){ + qCWarning(dcDenon) << "Invalid connection pointer" << device->id().toString(); + return; + } + m_denonConnection->deleteLater(); +} + + +void DevicePluginDenon::guhTimer() +{ + if (m_denonConnection.isNull()) + return; + + if (!m_denonConnection->connected()) { + m_denonConnection->connectDenon(); + } else { + m_denonConnection->sendData("PW?\rSI?\rMV?\r"); + } +} + +DeviceManager::DeviceError DevicePluginDenon::executeAction(Device *device, const Action &action) +{ + qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params(); + if (device->deviceClassId() == AVRX1000DeviceClassId) { + + // check connection state + if (m_denonConnection.isNull() || !m_denonConnection->connected()) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + // check if the requested action is our "update" action ... + if (action.actionTypeId() == powerActionTypeId) { + + // Print information that we are executing now the update action + qCDebug(dcDenon) << "set power action" << action.id(); + qCDebug(dcDenon) << "power: " << action.param("power").value().Bool; + + if (action.param("power").value().toBool() == true){ + QByteArray cmd = "PWON\r"; + qCDebug(dcDenon) << "Execute power: " << action.id() << cmd; + m_denonConnection->sendData(cmd); + } else { + QByteArray cmd = "PWSTANDBY\r"; + qCDebug(dcDenon) << "Execute power: " << action.id() << cmd; + m_denonConnection->sendData(cmd); + } + + return DeviceManager::DeviceErrorNoError; + + } else if (action.actionTypeId() == volumeActionTypeId) { + + QByteArray vol = action.param("volume").value().toByteArray(); + QByteArray cmd = "MV" + vol + "\r"; + + qCDebug(dcDenon) << "Execute volume" << action.id() << cmd; + m_denonConnection->sendData(cmd); + + return DeviceManager::DeviceErrorNoError; + + } else if (action.actionTypeId() == channelActionTypeId) { + + qCDebug(dcDenon) << "Execute update action" << action.id(); + QByteArray channel = action.param("channel").value().toByteArray(); + QByteArray cmd = "SI" + channel + "\r"; + + qCDebug(dcDenon) << "Change to channel:" << cmd; + m_denonConnection->sendData(cmd); + + return DeviceManager::DeviceErrorNoError; + } + return DeviceManager::DeviceErrorActionTypeNotFound; + } + return DeviceManager::DeviceErrorDeviceClassNotFound; +} + +void DevicePluginDenon::onConnectionChanged() +{ + // if the device is connected + if (m_denonConnection->connected()) { + // and from the first setup + if (m_asyncSetups.contains(m_denonConnection)) { + m_asyncSetups.removeAll(m_denonConnection); + m_denonConnection->sendData("PW?\rSI?\rMV?\r"); + emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusSuccess); + } + } + + // Set connection status + m_device->setStateValue(connectedStateTypeId, m_denonConnection->connected()); +} + +void DevicePluginDenon::onDataReceived(const QByteArray &data) +{ + qDebug(dcDenon) << "Data received" << data; + + // if there is no device, return + if (m_device.isNull()) + return; + + if (data.contains("MV") && !data.contains("MAX")){ + int index = data.indexOf("MV"); + int vol = data.mid(index+2, 2).toInt(); + + qDebug(dcDenon) << "Update volume:" << vol; + m_device->setStateValue(volumeStateTypeId, vol); + } + + if (data.contains("SI")) { + QString cmd = NULL; + if (data.contains("TUNER")) { + cmd = "TUNER"; + } else if (data.contains("DVD")) { + cmd = "DVD"; + } else if (data.contains("BD")) { + cmd = "BD"; + } else if (data.contains("TV")) { + cmd = "TV"; + } else if (data.contains("SAT/CBL")) { + cmd = "SAT/CBL"; + } else if (data.contains("MPLAY")) { + cmd = "MPLAY"; + } else if (data.contains("GAME")) { + cmd = "GAME"; + } else if (data.contains("AUX1")) { + cmd = "AUX1"; + } else if (data.contains("NET")) { + cmd = "NET"; + } else if (data.contains("PANDORA")) { + cmd = "PANDORA"; + } else if (data.contains("SIRIUSXM")) { + cmd = "SIRIUSXM"; + } else if (data.contains("SPOTIFY")) { + cmd = "SPOTIFY"; + } else if (data.contains("FLICKR")) { + cmd = "FLICKR"; + } else if (data.contains("FAVORITES")) { + cmd = "FAVORITES"; + } else if (data.contains("IRADIO")) { + cmd = "IRADIO"; + } else if (data.contains("SERVER")) { + cmd = "SERVER"; + } else if (data.contains("USB/IPOD")) { + cmd = "USB/IPOD"; + } else if (data.contains("IPD")) { + cmd = "IPD"; + } else if (data.contains("IRP")) { + cmd = "IRP"; + } else if (data.contains("FVP")) { + cmd = "FVP"; + } + + qDebug(dcDenon) << "Update channel:" << cmd; + m_device->setStateValue(channelStateTypeId, cmd); + } + + if (data.contains("PWON")) { + qDebug(dcDenon) << "Update power on"; + m_device->setStateValue(powerStateTypeId, true); + } else if (data.contains("PWSTANDBY")) { + qDebug(dcDenon) << "Update power off"; + m_device->setStateValue(powerStateTypeId, false); + } +} + +void DevicePluginDenon::onSocketError() +{ + // if there is no device, return + if (m_device.isNull()) + return; + + // Check if setup running for this device + if (m_asyncSetups.contains(m_denonConnection)) { + qCWarning(dcDenon()) << "Could not add device. The setup failed."; + emit deviceSetupFinished(m_device, DeviceManager::DeviceSetupStatusFailure); + // Delete the connection, the device will not be added and + // the connection will be created in the next setup + m_denonConnection->deleteLater(); + } +} + + + diff --git a/plugins/deviceplugins/denon/deviceplugindenon.h b/plugins/deviceplugins/denon/deviceplugindenon.h new file mode 100644 index 00000000..fa0a03b2 --- /dev/null +++ b/plugins/deviceplugins/denon/deviceplugindenon.h @@ -0,0 +1,68 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2016 Bernhard Trinnes * + * * + * This file is part of guh. * + * * + * Guh is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * Guh is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with guh. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEPLUGINDENON_H +#define DEVICEPLUGINDENON_H + +#include "devicemanager.h" +#include "plugin/deviceplugin.h" + + +#include +#include +#include +#include +#include + +#include "denonconnection.h" + +class DevicePluginDenon : public DevicePlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "deviceplugindenon.json") + Q_INTERFACES(DevicePlugin) + +public: + explicit DevicePluginDenon(); + + DeviceManager::HardwareResources requiredHardware() const override; + DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; + void deviceRemoved(Device *device) override; + + DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + void guhTimer() override; + +private: + QPointer m_device; + QPointer m_denonConnection; + QList m_asyncSetups; + + QHash m_asyncActions; + QHash m_asyncActionReplies; + +private slots: + void onConnectionChanged(); + void onDataReceived(const QByteArray &data); + void onSocketError(); +}; + +#endif // DEVICEPLUGINDENON_H diff --git a/plugins/deviceplugins/denon/deviceplugindenon.json b/plugins/deviceplugins/denon/deviceplugindenon.json new file mode 100644 index 00000000..f5da6710 --- /dev/null +++ b/plugins/deviceplugins/denon/deviceplugindenon.json @@ -0,0 +1,88 @@ +{ + "name": "Denon", + "idName": "Denon", + "id": "cd758269-dbbb-4ef0-80ab-48bd9a8a2765", + "vendors": [ + { + "id": "cf0a9644-2c13-4daf-85c1-ad88d6745b42", + "name": "Denon", + "idName": "denon", + "deviceClasses": [ + { + "deviceClassId": "1cd3d67e-aba0-450e-9e2a-483a1527aba6", + "idName": "AVRX1000", + "name": "AVR X1000", + "createMethods": ["user"], + "deviceIcon": "Hifi", + "basicTags": [ + "Device", + "Multimedia" + ], + "paramTypes": [ + { + "name": "ip", + "type" : "QString", + "inputType": "IPv4Address" + } + ], + "stateTypes": [ + { + "id": "4d1790bf-28c6-4c1f-8892-ba1a0ef140f5", + "idName": "connected", + "name": "connected", + "type": "bool" + }, + { + "name": "power", + "id": "1cdb6b54-6831-4900-95b2-c78f64497701", + "idName": "power", + "type": "bool", + "defaultValue": false, + "writable": true + }, + { + "name": "volume", + "id": "773636b9-304d-463a-8755-fc7488dc0ff3", + "idName": "volume", + "type": "int", + "unit": "Dezibel", + "defaultValue": 0, + "minValue": 0, + "maxValue": 80, + "writable": true + }, + { + "name": "channel", + "id": "f29ffa2c-31d6-4d88-b160-a38288c82ce1", + "idName": "channel", + "type": "QString", + "writable": true, + "possibleValues": [ + "TUNER", + "DVD", + "BD", + "TV", + "SAT/CBL", + "MPLAY", + "GAME", + "AUX1", + "NET", + "SPOTIFY", + "FLICKR", + "FAVORITES", + "IRADIO", + "SERVER", + "USB/IPOD", + "USB", + "IPD", + "IRP", + "FVP" + ], + "defaultValue": "TUNER" + } + ] + } + ] + } + ] +} diff --git a/plugins/deviceplugins/deviceplugins.pro b/plugins/deviceplugins/deviceplugins.pro index 9e79917e..df065012 100644 --- a/plugins/deviceplugins/deviceplugins.pro +++ b/plugins/deviceplugins/deviceplugins.pro @@ -25,3 +25,4 @@ SUBDIRS += elro \ osdomotics \ ws2812 \ orderbutton \ + denon \