diff --git a/denon/avrconnection.cpp b/denon/avrconnection.cpp new file mode 100644 index 00000000..24820976 --- /dev/null +++ b/denon/avrconnection.cpp @@ -0,0 +1,261 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2019 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * 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) any later version. * + * * + * 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 "avrconnection.h" +#include "extern-plugininfo.h" + +AvrConnection::AvrConnection(const QHostAddress &hostAddress, const int &port, QObject *parent) : + QObject(parent), + m_hostAddress(hostAddress), + m_port(port) +{ + m_socket = new QTcpSocket(this); + + connect(m_socket, &QTcpSocket::connected, this, &AvrConnection::onConnected); + connect(m_socket, &QTcpSocket::disconnected, this, &AvrConnection::onDisconnected); + connect(m_socket, &QTcpSocket::readyRead, this, &AvrConnection::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))); +} + +AvrConnection::~AvrConnection() +{ + m_socket->close(); +} + +void AvrConnection::connect() +{ + if (m_socket->state() == QAbstractSocket::ConnectingState) { + return; + } + m_socket->connectToHost(m_hostAddress, m_port); +} + +void AvrConnection::disconnect() +{ + m_socket->close(); +} + +QHostAddress AvrConnection::hostAddress() const +{ + return m_hostAddress; +} + +int AvrConnection::port() const +{ + return m_port; +} + +bool AvrConnection::connected() +{ + return m_socket->isOpen(); +} + +void AvrConnection::getAllStatus() +{ + sendCommand("PW?\rSI?\rMV?\rMS?\rMU?\r"); +} + +void AvrConnection::getChannel() +{ + sendCommand("SI?\r"); +} + +void AvrConnection::getVolume() +{ + sendCommand("MV?\r"); +} + +void AvrConnection::getMute() +{ + sendCommand("MU?\r"); +} + +void AvrConnection::getPower() +{ + sendCommand("PW?\r"); +} + +void AvrConnection::getSurroundMode() +{ + sendCommand("MS?\r"); +} + +void AvrConnection::sendCommand(const QByteArray &message) +{ + m_socket->write(message); +} + +void AvrConnection::setChannel(const QByteArray &channel) +{ + QByteArray cmd = "SI" + channel + "\r"; + qCDebug(dcDenon) << "Change to channel:" << cmd; + sendCommand(cmd); +} + +void AvrConnection::setVolume(int volume) +{ + qCDebug(dcDenon) << "Set volume" << volume; + QByteArray cmd = "MV" + QByteArray::number(volume) + "\r"; + sendCommand(cmd); +} + +void AvrConnection::setMute(bool mute) +{ + qCDebug(dcDenon) << "Set mute" << mute; + QByteArray cmd; + if (mute) { + cmd = "MUON\r"; + } else { + cmd = "MUOFF\r"; + } + sendCommand(cmd); +} + +void AvrConnection::setPower(bool power) +{ + qCDebug(dcDenon) << "Set power" << power; + QByteArray cmd; + if (power) { + cmd = "PWON\r"; + } else { + cmd = "PWSTANDBY\r"; + } + sendCommand(cmd); +} + +void AvrConnection::setSurroundMode(const QByteArray &surroundMode) +{ + qCDebug(dcDenon) << "Set surround mode" << surroundMode; + QByteArray cmd = "MS" + surroundMode + "\r"; + sendCommand(cmd); +} + +void AvrConnection::increaseVolume() +{ + qCDebug(dcDenon) << "Execute volume increase"; + QByteArray cmd = "MVUP\r"; + sendCommand(cmd); +} + +void AvrConnection::decreaseVolume() +{ + qCDebug(dcDenon) << "Execute volume decrease"; + QByteArray cmd = "MVDOWN\r"; + sendCommand(cmd); +} + +void AvrConnection::onConnected() +{ + qCDebug(dcDenon) << "connected successfully to" << hostAddress().toString() << port(); + emit connectionStatusChanged(true); +} + +void AvrConnection::onDisconnected() +{ + qCDebug(dcDenon) << "disconnected from" << hostAddress().toString() << port(); + emit connectionStatusChanged(false); +} + +void AvrConnection::onError(QAbstractSocket::SocketError socketError) +{ + qCWarning(dcDenon) << "socket error:" << socketError << m_socket->errorString(); + emit socketErrorOccured(socketError); +} + +void AvrConnection::readData() +{ + QByteArray data = m_socket->readAll(); + qCDebug(dcDenon) << "Data received" << data; + + if (data.contains("MV") && !data.contains("MAX")){ + int index = data.indexOf("MV"); + int volume = data.mid(index+2, 2).toInt(); + emit volumeChanged(volume); + } + + if (data.left(2).contains("SI")) { + QByteArray cmd; + 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"; + } + emit channelChanged(cmd); + } + + if (data.contains("PWON")) { + emit powerChanged(true); + } + if (data.contains("PWSTANDBY")) { + emit powerChanged(false); + } + if (data.contains("MUON")) { + emit muteChanged(false); + } + if (data.contains("MUOFF")) { + emit muteChanged(false); + } + + if (data.left(2).contains("MS")) { + data.remove(0, 2); + QByteArray cmd = data; + emit surroundModeChanged(cmd); + } +} diff --git a/denon/denonconnection.h b/denon/avrconnection.h similarity index 63% rename from denon/denonconnection.h rename to denon/avrconnection.h index 5241aafb..8bf2ab20 100644 --- a/denon/denonconnection.h +++ b/denon/avrconnection.h @@ -1,7 +1,7 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2016 Bernhard Trinnes * + * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2019 Bernhard Trinnes * * * * This file is part of nymea. * * * @@ -21,36 +21,48 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef DENONCONNECTION_H -#define DENONCONNECTION_H +#ifndef AVRCONNECTION_H +#define AVRCONNECTION_H #include #include #include -class DenonConnection : public QObject +class AvrConnection : public QObject { Q_OBJECT public: - explicit DenonConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = 0); - ~DenonConnection(); + explicit AvrConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = nullptr); + ~AvrConnection(); - void connectDenon(); - void disconnectDenon(); + void connect(); + void disconnect(); QHostAddress hostAddress() const; int port() const; - bool connected(); - void sendData(const QByteArray &message); + void getAllStatus(); + void getChannel(); + void getVolume(); + void getMute(); + void getPower(); + void getSurroundMode(); + void setChannel(const QByteArray &channel); + void setVolume(int volume); + void setMute(bool mute); + void setPower(bool power); + void setSurroundMode(const QByteArray &surroundMode); + + void increaseVolume(); + void decreaseVolume(); private: - QTcpSocket *m_socket; - + QTcpSocket *m_socket = nullptr; QHostAddress m_hostAddress; int m_port; - bool m_connected; + + void sendCommand(const QByteArray &message); private slots: void onConnected(); @@ -58,13 +70,14 @@ private slots: 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); - + void connectionStatusChanged(bool status); + void volumeChanged(int volume); + void muteChanged(bool mute); + void channelChanged(const QByteArray &channel); + void powerChanged(bool power); + void surroundModeChanged(const QByteArray &surroundMode); }; -#endif // DENONCONNECTION_H +#endif // AVRCONNECTION_H diff --git a/denon/denon.pro b/denon/denon.pro index 41adb02f..34ff584a 100644 --- a/denon/denon.pro +++ b/denon/denon.pro @@ -6,12 +6,12 @@ TARGET = $$qtLibraryTarget(nymea_deviceplugindenon) SOURCES += \ deviceplugindenon.cpp \ - denonconnection.cpp \ heos.cpp \ heosplayer.cpp \ + avrconnection.cpp HEADERS += \ deviceplugindenon.h \ - denonconnection.h \ heos.h \ heosplayer.h \ + avrconnection.h diff --git a/denon/denonconnection.cpp b/denon/denonconnection.cpp deleted file mode 100644 index d55e15ed..00000000 --- a/denon/denonconnection.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2016 Bernhard Trinnes * - * * - * This file is part of nymea. * - * * - * 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) any later version. * - * * - * 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 "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(); - emit dataReady(QString(data).toUtf8()); -} - -void DenonConnection::setConnected(const bool &connected) -{ - m_connected = connected; - emit connectionStatusChanged(); -} diff --git a/denon/deviceplugindenon.cpp b/denon/deviceplugindenon.cpp index 5a54ae3c..92e1e99e 100644 --- a/denon/deviceplugindenon.cpp +++ b/denon/deviceplugindenon.cpp @@ -43,7 +43,7 @@ #include "deviceplugindenon.h" #include "plugininfo.h" -#include "plugin/device.h" +#include "devices/device.h" #include "network/networkaccessmanager.h" #include "network/upnp/upnpdiscovery.h" #include "network/upnp/upnpdiscoveryreply.h" @@ -59,7 +59,7 @@ DevicePluginDenon::DevicePluginDenon() { } -DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) +Device::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) { Q_UNUSED(params) @@ -67,7 +67,7 @@ DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassI UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices("urn:schemas-upnp-org:device:MediaRenderer:1", "nymea", 7000); connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished); - return DeviceManager::DeviceErrorAsync; + return Device::DeviceErrorAsync; } if (deviceClassId == heosDeviceClassId) { @@ -80,9 +80,9 @@ DeviceManager::DeviceError DevicePluginDenon::discoverDevices(const DeviceClassI */ UpnpDiscoveryReply *reply = hardwareManager()->upnpDiscovery()->discoverDevices(); connect(reply, &UpnpDiscoveryReply::finished, this, &DevicePluginDenon::onUpnpDiscoveryFinished); - return DeviceManager::DeviceErrorAsync; + return Device::DeviceErrorAsync; } - return DeviceManager::DeviceErrorDeviceClassNotFound; + return Device::DeviceErrorDeviceClassNotFound; } Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) @@ -98,18 +98,22 @@ Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) QHostAddress address(device->paramValue(AVRX1000DeviceIpParamTypeId).toString()); if (address.isNull()) { qCWarning(dcDenon) << "Could not parse ip address" << device->paramValue(AVRX1000DeviceIpParamTypeId).toString(); - return DeviceManager::DeviceSetupStatusFailure; + return Device::DeviceSetupStatusFailure; } - DenonConnection *denonConnection = new DenonConnection(address, 23, this); - connect(denonConnection, &DenonConnection::connectionStatusChanged, this, &DevicePluginDenon::onAVRConnectionChanged); - connect(denonConnection, &DenonConnection::socketErrorOccured, this, &DevicePluginDenon::onAVRSocketError); - connect(denonConnection, &DenonConnection::dataReady, this, &DevicePluginDenon::onAVRDataReceived); + AvrConnection *denonConnection = new AvrConnection(address, 23, this); + connect(denonConnection, &AvrConnection::connectionStatusChanged, this, &DevicePluginDenon::onAvrConnectionChanged); + connect(denonConnection, &AvrConnection::socketErrorOccured, this, &DevicePluginDenon::onAvrSocketError); + connect(denonConnection, &AvrConnection::channelChanged, this, &DevicePluginDenon::onAvrChannelChanged); + connect(denonConnection, &AvrConnection::powerChanged, this, &DevicePluginDenon::onAvrPowerChanged); + connect(denonConnection, &AvrConnection::volumeChanged, this, &DevicePluginDenon::onAvrVolumeChanged); + connect(denonConnection, &AvrConnection::surroundModeChanged, this, &DevicePluginDenon::onAvrSurroundModeChanged); + connect(denonConnection, &AvrConnection::muteChanged, this, &DevicePluginDenon::onAvrMuteChanged); m_asyncSetups.append(denonConnection); - denonConnection->connectDenon(); - m_denonConnections.insert(device, denonConnection); - return DeviceManager::DeviceSetupStatusAsync; + denonConnection->connect(); + m_avrConnections.insert(device, denonConnection); + return Device::DeviceSetupStatusAsync; } if (device->deviceClassId() == heosDeviceClassId) { @@ -128,13 +132,13 @@ Device::DeviceSetupStatus DevicePluginDenon::setupDevice(Device *device) heos->connectHeos(); m_heos.insert(device, heos); - return DeviceManager::DeviceSetupStatusAsync; + return Device::DeviceSetupStatusAsync; } if (device->deviceClassId() == heosPlayerDeviceClassId) { - return DeviceManager::DeviceSetupStatusSuccess; + return Device::DeviceSetupStatusSuccess; } - return DeviceManager::DeviceSetupStatusFailure; + return Device::DeviceSetupStatusFailure; } void DevicePluginDenon::deviceRemoved(Device *device) @@ -142,17 +146,17 @@ void DevicePluginDenon::deviceRemoved(Device *device) qCDebug(dcDenon) << "Delete " << device->name(); if (device->deviceClassId() == AVRX1000DeviceClassId) { - DenonConnection *denonConnection = m_denonConnections.value(device); - m_denonConnections.remove(device); - denonConnection->disconnectDenon(); + AvrConnection *denonConnection = m_avrConnections.value(device); + m_avrConnections.remove(device); + denonConnection->disconnect(); denonConnection->deleteLater(); } if (device->deviceClassId() == heosDeviceClassId) { - if (m_denonConnections.contains(device)) { - DenonConnection *denonConnection = m_denonConnections.value(device); - m_denonConnections.remove(device); - denonConnection->disconnectDenon(); + if (m_avrConnections.contains(device)) { + AvrConnection *denonConnection = m_avrConnections.value(device); + m_avrConnections.remove(device); + denonConnection->disconnect(); denonConnection->deleteLater(); } } @@ -166,57 +170,44 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio { qCDebug(dcDenon) << "Execute action" << device->id() << action.id() << action.params(); if (device->deviceClassId() == AVRX1000DeviceClassId) { - DenonConnection *denonConnection = m_denonConnections.value(device); + AvrConnection *avrConnection = m_avrConnections.value(device); if (action.actionTypeId() == AVRX1000PowerActionTypeId) { - qCDebug(dcDenon) << "set power action" << action.id(); - qCDebug(dcDenon) << "power: " << action.param(AVRX1000PowerActionPowerParamTypeId).value().Bool; - - if (action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool() == true) { - QByteArray cmd = "PWON\r"; - qCDebug(dcDenon) << "Execute power: " << action.id() << cmd; - denonConnection->sendData(cmd); - } else { - QByteArray cmd = "PWSTANDBY\r"; - qCDebug(dcDenon) << "Execute power: " << action.id() << cmd; - denonConnection->sendData(cmd); - } - + bool power = action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool(); + avrConnection->setPower(power); return Device::DeviceErrorNoError; } else if (action.actionTypeId() == AVRX1000VolumeActionTypeId) { - QByteArray vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toByteArray(); - QByteArray cmd = "MV" + vol + "\r"; - - qCDebug(dcDenon) << "Execute volume" << action.id() << cmd; - denonConnection->sendData(cmd); - return DeviceManager::DeviceErrorNoError; + int vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toInt(); + avrConnection->setVolume(vol); + return Device::DeviceErrorNoError; } else if (action.actionTypeId() == AVRX1000ChannelActionTypeId) { qCDebug(dcDenon) << "Execute update action" << action.id(); QByteArray channel = action.param(AVRX1000ChannelActionChannelParamTypeId).value().toByteArray(); - QByteArray cmd = "SI" + channel + "\r"; - - qCDebug(dcDenon) << "Change to channel:" << cmd; - denonConnection->sendData(cmd); - return DeviceManager::DeviceErrorNoError; + avrConnection->setChannel(channel); + return Device::DeviceErrorNoError; } else if (action.actionTypeId() == AVRX1000IncreaseVolumeActionTypeId) { - QByteArray cmd = "MVUP\r"; - qCDebug(dcDenon) << "Execute volume increase" << action.id() << cmd; - denonConnection->sendData(cmd); - return DeviceManager::DeviceErrorNoError; + + avrConnection->increaseVolume(); + return Device::DeviceErrorNoError; } else if (action.actionTypeId() == AVRX1000DecreaseVolumeActionTypeId) { - QByteArray cmd = "MVDOWN\r"; - qCDebug(dcDenon) << "Execute volume decrease" << action.id() << cmd; - denonConnection->sendData(cmd); - return DeviceManager::DeviceErrorNoError; + + avrConnection->decreaseVolume(); + return Device::DeviceErrorNoError; + + } else if (action.actionTypeId() == AVRX1000SurroundModeActionTypeId) { + + QByteArray surroundMode = action.param(AVRX1000SurroundModeActionSurroundModeParamTypeId).value().toByteArray(); + avrConnection->setSurroundMode(surroundMode); + return Device::DeviceErrorNoError; } - return DeviceManager::DeviceErrorActionTypeNotFound; + return Device::DeviceErrorActionTypeNotFound; } if (device->deviceClassId() == heosPlayerDeviceClassId) { @@ -228,13 +219,13 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio if (action.actionTypeId() == heosPlayerVolumeActionTypeId) { int volume = action.param(heosPlayerVolumeActionVolumeParamTypeId).value().toInt(); heos->setVolume(playerId, volume); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerMuteActionTypeId) { bool mute = action.param(heosPlayerMuteActionMuteParamTypeId).value().toBool(); heos->setMute(playerId, mute); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerPlaybackStatusActionTypeId) { @@ -246,7 +237,7 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio } else if (playbackStatus == "pausing") { heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause); } - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerShuffleActionTypeId) { @@ -255,45 +246,45 @@ Device::DeviceError DevicePluginDenon::executeAction(Device *device, const Actio repeatMode = Heos::HeosRepeatMode::Off; heos->setPlayMode(playerId, repeatMode, shuffle); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerSkipBackActionTypeId) { heos->playPrevious(playerId); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerFastRewindActionTypeId) { - return DeviceManager::DeviceErrorActionTypeNotFound; + return Device::DeviceErrorActionTypeNotFound; } if (action.actionTypeId() == heosPlayerStopActionTypeId) { heos->setPlayerState(playerId, Heos::HeosPlayerState::Stop); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerPlayActionTypeId) { heos->setPlayerState(playerId, Heos::HeosPlayerState::Play); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerPauseActionTypeId) { heos->setPlayerState(playerId, Heos::HeosPlayerState::Pause); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } if (action.actionTypeId() == heosPlayerFastForwardActionTypeId) { - return DeviceManager::DeviceErrorActionTypeNotFound; + return Device::DeviceErrorActionTypeNotFound; } if (action.actionTypeId() == heosPlayerSkipNextActionTypeId) { heos->playNext(playerId); - return DeviceManager::DeviceErrorNoError; + return Device::DeviceErrorNoError; } - return DeviceManager::DeviceErrorActionTypeNotFound; + return Device::DeviceErrorActionTypeNotFound; } return Device::DeviceErrorDeviceClassNotFound; } @@ -324,13 +315,13 @@ void DevicePluginDenon::postSetupDevice(Device *device) void DevicePluginDenon::onPluginTimer() { - foreach(DenonConnection *denonConnection, m_denonConnections.values()) { + foreach(AvrConnection *denonConnection, m_avrConnections.values()) { if (!denonConnection->connected()) { - denonConnection->connectDenon(); + denonConnection->connect(); } - Device *device = m_denonConnections.key(denonConnection); + Device *device = m_avrConnections.key(denonConnection); if (device->deviceClassId() == AVRX1000DeviceClassId) { - denonConnection->sendData("PW?\rSI?\rMV?\r"); + denonConnection->getAllStatus(); } } @@ -360,113 +351,94 @@ void DevicePluginDenon::onPluginTimer() } } -void DevicePluginDenon::onAVRConnectionChanged() +void DevicePluginDenon::onAvrConnectionChanged(bool status) { - DenonConnection *denonConnection = static_cast(sender()); - Device *device = m_denonConnections.key(denonConnection); + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; if (device->deviceClassId() == AVRX1000DeviceClassId) { // if the device is connected - if (denonConnection->connected()) { + if (status) { // and from the first setup if (m_asyncSetups.contains(denonConnection)) { m_asyncSetups.removeAll(denonConnection); - denonConnection->sendData("PW?\rSI?\rMV?\r"); - emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); + + emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess); } } device->setStateValue(AVRX1000ConnectedStateTypeId, denonConnection->connected()); } } -void DevicePluginDenon::onAVRDataReceived(const QByteArray &data) +void DevicePluginDenon::onAvrVolumeChanged(int volume) { - DenonConnection *denonConnection = static_cast(sender()); - Device *device = m_denonConnections.key(denonConnection); - qCDebug(dcDenon) << "Data received" << data; + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; if (device->deviceClassId() == AVRX1000DeviceClassId) { - if (data.contains("MV") && !data.contains("MAX")){ - int index = data.indexOf("MV"); - int vol = data.mid(index+2, 2).toInt(); + device->setStateValue(AVRX1000VolumeStateTypeId, volume); + } +} - qCDebug(dcDenon) << "Update volume:" << vol; - device->setStateValue(AVRX1000VolumeStateTypeId, vol); - } +void DevicePluginDenon::onAvrMuteChanged(bool mute) +{ + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; - if (data.contains("SI")) { - QString cmd; - 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"; - } - qCDebug(dcDenon) << "Update channel:" << cmd; - device->setStateValue(AVRX1000ChannelStateTypeId, cmd); - } + if (device->deviceClassId() == AVRX1000DeviceClassId) { + device->setStateValue(AVRX1000MuteStateTypeId, mute); + } +} - if (data.contains("PWON")) { - qCDebug(dcDenon) << "Update power on"; - device->setStateValue(AVRX1000PowerStateTypeId, true); - } else if (data.contains("PWSTANDBY")) { - qCDebug(dcDenon) << "Update power off"; - device->setStateValue(AVRX1000PowerStateTypeId, false); - } +void DevicePluginDenon::onAvrPowerChanged(bool power) +{ + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; + + if (device->deviceClassId() == AVRX1000DeviceClassId) { + device->setStateValue(AVRX1000PowerStateTypeId, power); + } +} + +void DevicePluginDenon::onAvrSurroundModeChanged(const QByteArray &surroundMode) +{ + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; + + if (device->deviceClassId() == AVRX1000DeviceClassId) { + device->setStateValue(AVRX1000SurroundModeStateTypeId, surroundMode); } } -void DevicePluginDenon::onAVRSocketError() +void DevicePluginDenon::onAvrSocketError() { - DenonConnection *denonConnection = static_cast(sender()); - Device *device = m_denonConnections.key(denonConnection); + AvrConnection *denonConnection = static_cast(sender()); + Device *device = m_avrConnections.key(denonConnection); + if (!device) + return; + if (device->deviceClassId() == AVRX1000DeviceClassId) { // Check if setup running for this device if (m_asyncSetups.contains(denonConnection)) { m_asyncSetups.removeAll(denonConnection); qCWarning(dcDenon()) << "Could not add device. The setup failed."; - emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusFailure); + emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure); // Delete the connection, the device will not be added and // the connection will be created in the next setup denonConnection->deleteLater(); - m_denonConnections.remove(device); + m_avrConnections.remove(device); } } } @@ -510,7 +482,7 @@ void DevicePluginDenon::onUpnpDiscoveryFinished() } } //if (upnpDevice.modelName().contains("")) { - qCDebug(dcDenon) << "UPnP device found:" << upnpDevice.modelDescription() << upnpDevice.friendlyName() << upnpDevice.hostAddress().toString() << upnpDevice.modelName() << upnpDevice.manufacturer() << upnpDevice.serialNumber(); + qCDebug(dcDenon) << "UPnP device found:" << upnpDevice.modelDescription() << upnpDevice.friendlyName() << upnpDevice.hostAddress().toString() << upnpDevice.modelName() << upnpDevice.manufacturer() << upnpDevice.serialNumber(); //} } if (!heosDescriptors.isEmpty()) { @@ -527,7 +499,7 @@ void DevicePluginDenon::onHeosConnectionChanged() heos->registerForChangeEvents(true); Device *device = m_heos.key(heos); if (!device->setupComplete() && heos->connected()) { - emit deviceSetupFinished(device, DeviceManager::DeviceSetupStatusSuccess); + emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess); } } @@ -623,3 +595,4 @@ void DevicePluginDenon::onHeosNowPlayingMediaStatusReceived(int playerId, QStrin break; } } + diff --git a/denon/deviceplugindenon.h b/denon/deviceplugindenon.h index 7da3f97a..42421a14 100644 --- a/denon/deviceplugindenon.h +++ b/denon/deviceplugindenon.h @@ -24,10 +24,9 @@ #ifndef DEVICEPLUGINDENON_H #define DEVICEPLUGINDENON_H -#include "devicemanager.h" -#include "plugin/deviceplugin.h" +#include "devices/deviceplugin.h" #include "plugintimer.h" -#include "denonconnection.h" +#include "avrconnection.h" #include "heos.h" #include @@ -47,18 +46,18 @@ class DevicePluginDenon : public DevicePlugin public: explicit DevicePluginDenon(); - DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; - DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; + Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; + Device::DeviceSetupStatus setupDevice(Device *device) override; void postSetupDevice(Device * device) override; - DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; + Device::DeviceError executeAction(Device *device, const Action &action) override; void deviceRemoved(Device *device) override; private: PluginTimer *m_pluginTimer = nullptr; - QHash m_denonConnections; + QHash m_avrConnections; QHash m_heos; - QList m_asyncSetups; + QList m_asyncSetups; QHash m_playerIds; QHash m_discoveredPlayerIds; @@ -67,11 +66,6 @@ private: private slots: void onPluginTimer(); - - void onAVRConnectionChanged(); - void onAVRDataReceived(const QByteArray &data); - void onAVRSocketError(); - void onUpnpDiscoveryFinished(); void onHeosConnectionChanged(); @@ -82,6 +76,14 @@ private slots: void onHeosMuteStatusReceived(int playerId, bool mute); void onHeosVolumeStatusReceived(int playerId, int volume); void onHeosNowPlayingMediaStatusReceived(int playerId, QString source, QString artist, QString album, QString Song, QString artwork); + + void onAvrConnectionChanged(bool status); + void onAvrSocketError(); + void onAvrVolumeChanged(int volume); + void onAvrChannelChanged(const QByteArray &channel); + void onAvrMuteChanged(bool mute); + void onAvrPowerChanged(bool power); + void onAvrSurroundModeChanged(const QByteArray &surroundMode); }; #endif // DEVICEPLUGINDENON_H diff --git a/denon/deviceplugindenon.json b/denon/deviceplugindenon.json index f6d6d0a8..562fe538 100644 --- a/denon/deviceplugindenon.json +++ b/denon/deviceplugindenon.json @@ -94,6 +94,32 @@ "FVP" ], "defaultValue": "TUNER" + }, + { + "displayName": "Surround mode", + "id": "4f203bdd-691c-4384-a934-2d49a5448f0a", + "name": "surroundMode", + "displayNameEvent": "Surround mode changed", + "displayNameAction": "Set surround mode", + "type": "QString", + "writable": true, + "possibleValues": [ + "MOVIE", + "MUSIC", + "GAME", + "PURE DIRECT", + "DIRECT", + "STEREO", + "STANDARD", + "DOLBY DIGITAL", + "DTS SUROUND", + "MCH STEREO", + "ROCK ARENA", + "JAZZ CLUB", + "MONO MOVIE", + "MATRIX" + ], + "defaultValue": "MOVIE" } ], "actionTypes": [ @@ -156,8 +182,8 @@ { "id": "4d1790bf-28c6-4c1f-8892-ba1a0ef140f5", "name": "connected", - "displayName": "connected", - "displayNameEvent": "connected changed", + "displayName": "Connected", + "displayNameEvent": "Connected changed", "defaultValue": false, "type": "bool" } @@ -200,7 +226,7 @@ "id": "9a4e527e-057c-4b19-8a02-605cc8349f5e", "name": "connected", "displayName": "connected", - "displayNameEvent": "connected changed", + "displayNameEvent": "Connected changed", "type": "bool", "defaultValue": false, "cached": false @@ -208,9 +234,9 @@ { "id": "fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f", "name": "mute", - "displayName": "mute", - "displayNameEvent": "mute changed", - "displayNameAction": "set mute", + "displayName": "Mute", + "displayNameEvent": "Mute changed", + "displayNameAction": "Set mute", "type": "bool", "defaultValue": false, "cached": false, @@ -219,7 +245,7 @@ { "id": "6d4886a1-fa5d-4889-96c5-7a1c206f59be", "name": "volume", - "displayName": "volume", + "displayName": "Volume", "displayNameEvent": "volume changed", "displayNameAction": "set volume", "type": "int",