denon avr fixed discovery and added async actions
This commit is contained in:
parent
99b00d5ac8
commit
c03d67b9ff
@ -1,4 +1,4 @@
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
*
|
*
|
||||||
* Copyright 2013 - 2020, nymea GmbH
|
* Copyright 2013 - 2020, nymea GmbH
|
||||||
* Contact: contact@nymea.io
|
* Contact: contact@nymea.io
|
||||||
@ -43,6 +43,23 @@ AvrConnection::AvrConnection(const QHostAddress &hostAddress, const int &port, Q
|
|||||||
connect(m_socket, &QTcpSocket::readyRead, this, &AvrConnection::readData);
|
connect(m_socket, &QTcpSocket::readyRead, this, &AvrConnection::readData);
|
||||||
// Note: error signal will be interpreted as function, not as signal in C++11
|
// 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)));
|
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||||
|
|
||||||
|
m_commandTimer = new QTimer(this);
|
||||||
|
m_commandTimer->start(50); // 50ms is the minimum request interval specified
|
||||||
|
|
||||||
|
connect(m_commandTimer, &QTimer::timeout, this, [this] {
|
||||||
|
if (!m_commandBuffer.isEmpty()) {
|
||||||
|
QPair<QUuid, QByteArray> command = m_commandBuffer.takeFirst();
|
||||||
|
if (m_socket->write(command.second) == -1) {
|
||||||
|
emit commandExecuted(command.first, false);
|
||||||
|
qCWarning(dcDenon()) << "Could not execute command" << command.second;
|
||||||
|
} else {
|
||||||
|
emit commandExecuted(command.first, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_commandTimer->stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AvrConnection::~AvrConnection()
|
AvrConnection::~AvrConnection()
|
||||||
@ -78,56 +95,62 @@ bool AvrConnection::connected()
|
|||||||
return m_socket->isOpen();
|
return m_socket->isOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getAllStatus()
|
QUuid AvrConnection::getChannel()
|
||||||
{
|
{
|
||||||
sendCommand("PW?\rSI?\rMV?\rMS?\rMU?\r");
|
return sendCommand("SI?\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getChannel()
|
QUuid AvrConnection::getVolume()
|
||||||
{
|
{
|
||||||
sendCommand("SI?\r");
|
return sendCommand("MV?\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getVolume()
|
QUuid AvrConnection::getMute()
|
||||||
{
|
{
|
||||||
sendCommand("MV?\r");
|
return sendCommand("MU?\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getMute()
|
QUuid AvrConnection::getPower()
|
||||||
{
|
{
|
||||||
sendCommand("MU?\r");
|
return sendCommand("PW?\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getPower()
|
QUuid AvrConnection::getSurroundMode()
|
||||||
{
|
{
|
||||||
sendCommand("PW?\r");
|
return sendCommand("MS?\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::getSurroundMode()
|
QUuid AvrConnection::getPlayBackInfo()
|
||||||
{
|
{
|
||||||
sendCommand("MS?\r");
|
return sendCommand("NSE\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::sendCommand(const QByteArray &message)
|
QUuid AvrConnection::sendCommand(const QByteArray &message)
|
||||||
{
|
{
|
||||||
m_socket->write(message);
|
QUuid commandId = QUuid::createUuid();
|
||||||
|
|
||||||
|
if (!m_commandTimer->isActive())
|
||||||
|
m_commandTimer->start(50);
|
||||||
|
|
||||||
|
m_commandBuffer.append(QPair<QUuid, QByteArray>(commandId, message));
|
||||||
|
return commandId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::setChannel(const QByteArray &channel)
|
QUuid AvrConnection::setChannel(const QByteArray &channel)
|
||||||
{
|
{
|
||||||
QByteArray cmd = "SI" + channel + "\r";
|
QByteArray cmd = "SI" + channel + "\r";
|
||||||
qCDebug(dcDenon) << "Change to channel:" << cmd;
|
qCDebug(dcDenon) << "Change to channel:" << channel;
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::setVolume(int volume)
|
QUuid AvrConnection::setVolume(int volume)
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Set volume" << volume;
|
qCDebug(dcDenon) << "Set volume" << volume;
|
||||||
QByteArray cmd = "MV" + QByteArray::number(volume) + "\r";
|
QByteArray cmd = "MV" + QByteArray::number(volume) + "\r";
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::setMute(bool mute)
|
QUuid AvrConnection::setMute(bool mute)
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Set mute" << mute;
|
qCDebug(dcDenon) << "Set mute" << mute;
|
||||||
QByteArray cmd;
|
QByteArray cmd;
|
||||||
@ -136,10 +159,10 @@ void AvrConnection::setMute(bool mute)
|
|||||||
} else {
|
} else {
|
||||||
cmd = "MUOFF\r";
|
cmd = "MUOFF\r";
|
||||||
}
|
}
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::setPower(bool power)
|
QUuid AvrConnection::setPower(bool power)
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Set power" << power;
|
qCDebug(dcDenon) << "Set power" << power;
|
||||||
QByteArray cmd;
|
QByteArray cmd;
|
||||||
@ -148,28 +171,125 @@ void AvrConnection::setPower(bool power)
|
|||||||
} else {
|
} else {
|
||||||
cmd = "PWSTANDBY\r";
|
cmd = "PWSTANDBY\r";
|
||||||
}
|
}
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::setSurroundMode(const QByteArray &surroundMode)
|
QUuid AvrConnection::setSurroundMode(const QByteArray &surroundMode)
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Set surround mode" << surroundMode;
|
qCDebug(dcDenon) << "Set surround mode" << surroundMode;
|
||||||
QByteArray cmd = "MS" + surroundMode + "\r";
|
QByteArray cmd = "MS" + surroundMode + "\r";
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::increaseVolume()
|
QUuid AvrConnection::enableToneControl(bool enabled)
|
||||||
|
{
|
||||||
|
QByteArray cmd;
|
||||||
|
if (enabled) {
|
||||||
|
cmd = "PSTONE CTRL ON\r";
|
||||||
|
} else {
|
||||||
|
cmd = "PSTONE CTRL OFF\r";
|
||||||
|
}
|
||||||
|
return sendCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::setBassLevel(int level)
|
||||||
|
{
|
||||||
|
QByteArray cmd;
|
||||||
|
cmd = "PSBAS ";
|
||||||
|
cmd.append(50 + level);
|
||||||
|
cmd.append("\r");
|
||||||
|
return sendCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::setTrebleLevel(int level)
|
||||||
|
{
|
||||||
|
QByteArray cmd;
|
||||||
|
cmd = "PSTRE ";
|
||||||
|
cmd.append(50 + level);
|
||||||
|
cmd.append("\r");
|
||||||
|
return sendCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::getBassLevel()
|
||||||
|
{
|
||||||
|
return sendCommand("PSBAS ?\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::getTrebleLevel()
|
||||||
|
{
|
||||||
|
return sendCommand("PSTRE ?\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::getToneControl()
|
||||||
|
{
|
||||||
|
return sendCommand("PSTONE CTRL ?\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::play()
|
||||||
|
{
|
||||||
|
return sendCommand("NS9A\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::pause()
|
||||||
|
{
|
||||||
|
return sendCommand("NS9B\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::stop()
|
||||||
|
{
|
||||||
|
return sendCommand("NS9C\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::skipNext()
|
||||||
|
{
|
||||||
|
return sendCommand("NS9D\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::skipBack()
|
||||||
|
{
|
||||||
|
return sendCommand("NS9E\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::setRandom(bool on)
|
||||||
|
{
|
||||||
|
QByteArray cmd;
|
||||||
|
if (on) {
|
||||||
|
cmd = "NS9K\r";
|
||||||
|
} else {
|
||||||
|
cmd = "NS9M\r";
|
||||||
|
}
|
||||||
|
return sendCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::setRepeat(AvrConnection::RepeatMode mode)
|
||||||
|
{
|
||||||
|
QByteArray cmd;
|
||||||
|
switch (mode) {
|
||||||
|
case RepeatModeRepeatAll:
|
||||||
|
cmd = "NS9I\r";
|
||||||
|
break;
|
||||||
|
case RepeatModeRepeatOne:
|
||||||
|
cmd = "NS9H\r";
|
||||||
|
break;
|
||||||
|
case RepeatModeRepeatNone:
|
||||||
|
cmd = "NS9J\r";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return sendCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid AvrConnection::increaseVolume()
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Execute volume increase";
|
qCDebug(dcDenon) << "Execute volume increase";
|
||||||
QByteArray cmd = "MVUP\r";
|
QByteArray cmd = "MVUP\r";
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::decreaseVolume()
|
QUuid AvrConnection::decreaseVolume()
|
||||||
{
|
{
|
||||||
qCDebug(dcDenon) << "Execute volume decrease";
|
qCDebug(dcDenon) << "Execute volume decrease";
|
||||||
QByteArray cmd = "MVDOWN\r";
|
QByteArray cmd = "MVDOWN\r";
|
||||||
sendCommand(cmd);
|
return sendCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvrConnection::onConnected()
|
void AvrConnection::onConnected()
|
||||||
@ -192,77 +312,112 @@ void AvrConnection::onError(QAbstractSocket::SocketError socketError)
|
|||||||
|
|
||||||
void AvrConnection::readData()
|
void AvrConnection::readData()
|
||||||
{
|
{
|
||||||
QByteArray data = m_socket->readAll();
|
QString data = QString(m_socket->readAll());
|
||||||
qCDebug(dcDenon) << "Data received" << data;
|
|
||||||
|
|
||||||
if (data.contains("MV") && !data.contains("MAX")){
|
QStringList lines = data.split('\r');
|
||||||
int index = data.indexOf("MV");
|
foreach (QString line, lines) {
|
||||||
int volume = data.mid(index+2, 2).toInt();
|
if(line.isEmpty())
|
||||||
emit volumeChanged(volume);
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (data.left(2).contains("SI")) {
|
qCDebug(dcDenon) << "Data received" << line;
|
||||||
QByteArray cmd;
|
if (line.contains("MV") && !data.contains("MAX")){
|
||||||
if (data.contains("TUNER")) {
|
int index = data.indexOf("MV");
|
||||||
cmd = "TUNER";
|
int volume = data.mid(index+2, 2).toInt();
|
||||||
} else if (data.contains("DVD")) {
|
emit volumeChanged(volume);
|
||||||
cmd = "DVD";
|
|
||||||
} else if (data.contains("BD")) {
|
} else if (line.left(2).contains("SI")) {
|
||||||
cmd = "BD";
|
QByteArray cmd;
|
||||||
} else if (data.contains("TV")) {
|
if (data.contains("TUNER")) {
|
||||||
cmd = "TV";
|
cmd = "TUNER";
|
||||||
} else if (data.contains("SAT/CBL")) {
|
} else if (data.contains("DVD")) {
|
||||||
cmd = "SAT/CBL";
|
cmd = "DVD";
|
||||||
} else if (data.contains("MPLAY")) {
|
} else if (data.contains("BD")) {
|
||||||
cmd = "MPLAY";
|
cmd = "BD";
|
||||||
} else if (data.contains("GAME")) {
|
} else if (data.contains("TV")) {
|
||||||
cmd = "GAME";
|
cmd = "TV";
|
||||||
} else if (data.contains("AUX1")) {
|
} else if (data.contains("SAT/CBL")) {
|
||||||
cmd = "AUX1";
|
cmd = "SAT/CBL";
|
||||||
} else if (data.contains("NET")) {
|
} else if (data.contains("MPLAY")) {
|
||||||
cmd = "NET";
|
cmd = "MPLAY";
|
||||||
} else if (data.contains("PANDORA")) {
|
} else if (data.contains("GAME")) {
|
||||||
cmd = "PANDORA";
|
cmd = "GAME";
|
||||||
} else if (data.contains("SIRIUSXM")) {
|
} else if (data.contains("AUX1")) {
|
||||||
cmd = "SIRIUSXM";
|
cmd = "AUX1";
|
||||||
} else if (data.contains("SPOTIFY")) {
|
} else if (data.contains("NET")) {
|
||||||
cmd = "SPOTIFY";
|
cmd = "NET";
|
||||||
} else if (data.contains("FLICKR")) {
|
} else if (data.contains("PANDORA")) {
|
||||||
cmd = "FLICKR";
|
cmd = "PANDORA";
|
||||||
} else if (data.contains("FAVORITES")) {
|
} else if (data.contains("SIRIUSXM")) {
|
||||||
cmd = "FAVORITES";
|
cmd = "SIRIUSXM";
|
||||||
} else if (data.contains("IRADIO")) {
|
} else if (data.contains("SPOTIFY")) {
|
||||||
cmd = "IRADIO";
|
cmd = "SPOTIFY";
|
||||||
} else if (data.contains("SERVER")) {
|
} else if (data.contains("FLICKR")) {
|
||||||
cmd = "SERVER";
|
cmd = "FLICKR";
|
||||||
} else if (data.contains("USB/IPOD")) {
|
} else if (data.contains("FAVORITES")) {
|
||||||
cmd = "USB/IPOD";
|
cmd = "FAVORITES";
|
||||||
} else if (data.contains("IPD")) {
|
} else if (data.contains("IRADIO")) {
|
||||||
cmd = "IPD";
|
cmd = "IRADIO";
|
||||||
} else if (data.contains("IRP")) {
|
} else if (data.contains("SERVER")) {
|
||||||
cmd = "IRP";
|
cmd = "SERVER";
|
||||||
} else if (data.contains("FVP")) {
|
} else if (data.contains("USB/IPOD")) {
|
||||||
cmd = "FVP";
|
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);
|
||||||
|
} else if (data.contains("PWON")) {
|
||||||
|
emit powerChanged(true);
|
||||||
|
} else if (data.contains("PWSTANDBY")) {
|
||||||
|
emit powerChanged(false);
|
||||||
|
} else if (data.contains("MUON")) {
|
||||||
|
emit muteChanged(true);
|
||||||
|
} else if (data.contains("MUOFF")) {
|
||||||
|
emit muteChanged(false);
|
||||||
|
} else if (data.left(2).contains("MS")) {
|
||||||
|
QString surroundMode = data.remove(0, 2).trimmed();
|
||||||
|
qCDebug(dcDenon()) << "Surround mode changed" << surroundMode;
|
||||||
|
emit surroundModeChanged(surroundMode);
|
||||||
|
|
||||||
|
} else if (data.left(4).contains("NSE0")) {
|
||||||
|
QString nowPlaying = QString(data).remove(0, 4).trimmed();
|
||||||
|
qCDebug(dcDenon()) << "Playbackstatus" << nowPlaying;
|
||||||
|
if (nowPlaying.contains("Now Playing")) {
|
||||||
|
emit playBackModeChanged(PlayBackMode::PlayBackModePlaying);
|
||||||
|
} else {
|
||||||
|
emit playBackModeChanged(PlayBackMode::PlayBackModeStopped);
|
||||||
|
}
|
||||||
|
} else if (data.left(4).contains("NSE1")) {
|
||||||
|
QString song = QString(data).remove(0, 4).trimmed();
|
||||||
|
qCDebug(dcDenon()) << "Song" << song;
|
||||||
|
emit songChanged(song);
|
||||||
|
} else if (data.left(4).contains("NSE2")) {
|
||||||
|
QString artist = QString(data).remove(0, 4).trimmed();
|
||||||
|
qCDebug(dcDenon()) << "Artist" << artist;
|
||||||
|
emit artistChanged(artist);
|
||||||
|
} else if (data.left(4).contains("NSE4")) {
|
||||||
|
QString album = QString(data).remove(0, 4).trimmed();
|
||||||
|
qCDebug(dcDenon()) << "Album" << album;
|
||||||
|
emit albumChanged(album);
|
||||||
|
} else if (data.contains("PSTONE CTRL ON")) {
|
||||||
|
qCDebug(dcDenon()) << "Tone control is on";
|
||||||
|
emit toneControlEnabledChanged(true);
|
||||||
|
} else if (data.contains("PSTONE CTRL OFF")) {
|
||||||
|
qCDebug(dcDenon()) << "Tone control is off";
|
||||||
|
emit toneControlEnabledChanged(false);
|
||||||
|
} else if (data.contains("PSBAS")) {
|
||||||
|
int index = data.indexOf("PSBAS");
|
||||||
|
int bass = data.mid(index+6, 2).toInt() - 50;
|
||||||
|
qCDebug(dcDenon()) << "Bass level" << bass;
|
||||||
|
emit bassLevelChanged(bass);
|
||||||
|
} else if (data.contains("PSTRE")) {
|
||||||
|
int index = data.indexOf("PSTRE");
|
||||||
|
int treble = data.mid(index+6, 2).toInt() - 50;
|
||||||
|
qCDebug(dcDenon()) << "Treble level" << treble;
|
||||||
|
emit trebleLevelChanged(treble);
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,11 +34,25 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
class AvrConnection : public QObject
|
class AvrConnection : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
enum RepeatMode {
|
||||||
|
RepeatModeRepeatAll,
|
||||||
|
RepeatModeRepeatOne,
|
||||||
|
RepeatModeRepeatNone
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PlayBackMode {
|
||||||
|
PlayBackModePlaying,
|
||||||
|
PlayBackModeStopped,
|
||||||
|
PlayBackModePaused
|
||||||
|
};
|
||||||
|
|
||||||
explicit AvrConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = nullptr);
|
explicit AvrConnection(const QHostAddress &hostAddress, const int &port = 23, QObject *parent = nullptr);
|
||||||
~AvrConnection();
|
~AvrConnection();
|
||||||
|
|
||||||
@ -49,27 +63,44 @@ public:
|
|||||||
int port() const;
|
int port() const;
|
||||||
bool connected();
|
bool connected();
|
||||||
|
|
||||||
void getAllStatus();
|
QUuid getChannel();
|
||||||
void getChannel();
|
QUuid getVolume();
|
||||||
void getVolume();
|
QUuid getMute();
|
||||||
void getMute();
|
QUuid getPower();
|
||||||
void getPower();
|
QUuid getSurroundMode();
|
||||||
void getSurroundMode();
|
QUuid getPlayBackInfo();
|
||||||
|
|
||||||
void setChannel(const QByteArray &channel);
|
QUuid setChannel(const QByteArray &channel);
|
||||||
void setVolume(int volume);
|
QUuid setVolume(int volume);
|
||||||
void setMute(bool mute);
|
QUuid setMute(bool mute);
|
||||||
void setPower(bool power);
|
QUuid setPower(bool power);
|
||||||
void setSurroundMode(const QByteArray &surroundMode);
|
QUuid setSurroundMode(const QByteArray &surroundMode);
|
||||||
|
QUuid enableToneControl(bool enabled);
|
||||||
|
QUuid setBassLevel(int level); //-6 to +6
|
||||||
|
QUuid setTrebleLevel(int level); //-6 to +6
|
||||||
|
|
||||||
void increaseVolume();
|
QUuid getBassLevel();
|
||||||
void decreaseVolume();
|
QUuid getTrebleLevel();
|
||||||
|
QUuid getToneControl();
|
||||||
|
|
||||||
|
QUuid play();
|
||||||
|
QUuid pause();
|
||||||
|
QUuid stop();
|
||||||
|
QUuid skipNext();
|
||||||
|
QUuid skipBack();
|
||||||
|
QUuid setRandom(bool on);
|
||||||
|
QUuid setRepeat(RepeatMode mode);
|
||||||
|
|
||||||
|
QUuid increaseVolume();
|
||||||
|
QUuid decreaseVolume();
|
||||||
private:
|
private:
|
||||||
|
QTimer *m_commandTimer = nullptr;
|
||||||
QTcpSocket *m_socket = nullptr;
|
QTcpSocket *m_socket = nullptr;
|
||||||
QHostAddress m_hostAddress;
|
QHostAddress m_hostAddress;
|
||||||
int m_port;
|
int m_port;
|
||||||
|
QList<QPair<QUuid, QByteArray>> m_commandBuffer;
|
||||||
|
|
||||||
void sendCommand(const QByteArray &message);
|
QUuid sendCommand(const QByteArray &message);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onConnected();
|
void onConnected();
|
||||||
@ -80,11 +111,19 @@ private slots:
|
|||||||
signals:
|
signals:
|
||||||
void socketErrorOccured(QAbstractSocket::SocketError socketError);
|
void socketErrorOccured(QAbstractSocket::SocketError socketError);
|
||||||
void connectionStatusChanged(bool status);
|
void connectionStatusChanged(bool status);
|
||||||
|
void commandExecuted(const QUuid &commandId, bool success);
|
||||||
void volumeChanged(int volume);
|
void volumeChanged(int volume);
|
||||||
void muteChanged(bool mute);
|
void muteChanged(bool mute);
|
||||||
void channelChanged(const QByteArray &channel);
|
void channelChanged(const QString &channel);
|
||||||
void powerChanged(bool power);
|
void powerChanged(bool power);
|
||||||
void surroundModeChanged(const QByteArray &surroundMode);
|
void surroundModeChanged(const QString &surroundMode);
|
||||||
|
void songChanged(const QString &song);
|
||||||
|
void artistChanged(const QString &artist);
|
||||||
|
void albumChanged(const QString &album);
|
||||||
|
void playBackModeChanged(AvrConnection::PlayBackMode);
|
||||||
|
void bassLevelChanged(int level);
|
||||||
|
void trebleLevelChanged(int level);
|
||||||
|
void toneControlEnabledChanged(bool enabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AVRCONNECTION_H
|
#endif // AVRCONNECTION_H
|
||||||
|
|||||||
@ -58,14 +58,15 @@ void IntegrationPluginDenon::init()
|
|||||||
void IntegrationPluginDenon::discoverThings(ThingDiscoveryInfo *info)
|
void IntegrationPluginDenon::discoverThings(ThingDiscoveryInfo *info)
|
||||||
{
|
{
|
||||||
if (info->thingClassId() == AVRX1000ThingClassId) {
|
if (info->thingClassId() == AVRX1000ThingClassId) {
|
||||||
if (!hardwareManager()->zeroConfController()->available() || !hardwareManager()->zeroConfController()->enabled()) {
|
|
||||||
//: Error discovering Denon things
|
|
||||||
info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("Thing discovery is not available."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_serviceBrowser) {
|
if (!m_serviceBrowser) {
|
||||||
m_serviceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser();;
|
m_serviceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hardwareManager()->zeroConfController()->available()) {
|
||||||
|
qCDebug(dcDenon()) << "Error discovering Denon things. Available:" << hardwareManager()->zeroConfController()->available();
|
||||||
|
info->finish(Thing::ThingErrorHardwareNotAvailable, "Thing discovery not possible");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTimer::singleShot(2000, info, [this, info](){
|
QTimer::singleShot(2000, info, [this, info](){
|
||||||
@ -196,16 +197,30 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info)
|
|||||||
AvrConnection *denonConnection = new AvrConnection(address, 23, this);
|
AvrConnection *denonConnection = new AvrConnection(address, 23, this);
|
||||||
connect(denonConnection, &AvrConnection::connectionStatusChanged, this, &IntegrationPluginDenon::onAvrConnectionChanged);
|
connect(denonConnection, &AvrConnection::connectionStatusChanged, this, &IntegrationPluginDenon::onAvrConnectionChanged);
|
||||||
connect(denonConnection, &AvrConnection::socketErrorOccured, this, &IntegrationPluginDenon::onAvrSocketError);
|
connect(denonConnection, &AvrConnection::socketErrorOccured, this, &IntegrationPluginDenon::onAvrSocketError);
|
||||||
|
connect(denonConnection, &AvrConnection::commandExecuted, this, &IntegrationPluginDenon::onAvrCommandExecuted);
|
||||||
connect(denonConnection, &AvrConnection::channelChanged, this, &IntegrationPluginDenon::onAvrChannelChanged);
|
connect(denonConnection, &AvrConnection::channelChanged, this, &IntegrationPluginDenon::onAvrChannelChanged);
|
||||||
connect(denonConnection, &AvrConnection::powerChanged, this, &IntegrationPluginDenon::onAvrPowerChanged);
|
connect(denonConnection, &AvrConnection::powerChanged, this, &IntegrationPluginDenon::onAvrPowerChanged);
|
||||||
connect(denonConnection, &AvrConnection::volumeChanged, this, &IntegrationPluginDenon::onAvrVolumeChanged);
|
connect(denonConnection, &AvrConnection::volumeChanged, this, &IntegrationPluginDenon::onAvrVolumeChanged);
|
||||||
connect(denonConnection, &AvrConnection::surroundModeChanged, this, &IntegrationPluginDenon::onAvrSurroundModeChanged);
|
connect(denonConnection, &AvrConnection::surroundModeChanged, this, &IntegrationPluginDenon::onAvrSurroundModeChanged);
|
||||||
connect(denonConnection, &AvrConnection::muteChanged, this, &IntegrationPluginDenon::onAvrMuteChanged);
|
connect(denonConnection, &AvrConnection::muteChanged, this, &IntegrationPluginDenon::onAvrMuteChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::artistChanged, this, &IntegrationPluginDenon::onAvrArtistChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::albumChanged, this, &IntegrationPluginDenon::onAvrAlbumChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::songChanged, this, &IntegrationPluginDenon::onAvrSongChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::playBackModeChanged, this, &IntegrationPluginDenon::onAvrPlayBackModeChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::bassLevelChanged, this, &IntegrationPluginDenon::onAvrBassLevelChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::trebleLevelChanged, this, &IntegrationPluginDenon::onAvrTrebleLevelChanged);
|
||||||
|
connect(denonConnection, &AvrConnection::toneControlEnabledChanged, this, &IntegrationPluginDenon::onAvrToneControlEnabledChanged);
|
||||||
|
|
||||||
m_avrConnections.insert(thing->id(), denonConnection);
|
m_avrConnections.insert(thing->id(), denonConnection);
|
||||||
m_asyncAvrSetups.insert(denonConnection, info);
|
m_asyncAvrSetups.insert(denonConnection, info);
|
||||||
// In case the setup is cancelled before we finish it...
|
// In case the setup is cancelled before we finish it...
|
||||||
connect(info, &QObject::destroyed, this, [this, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); });
|
connect(info, &QObject::destroyed, this, [this, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); });
|
||||||
|
connect(info, &ThingSetupInfo::aborted, this, [this, thing] () {
|
||||||
|
if (m_avrConnections.contains(thing->id())) {
|
||||||
|
AvrConnection *connection = m_avrConnections.take(thing->id());
|
||||||
|
connection->deleteLater();
|
||||||
|
}
|
||||||
|
});
|
||||||
denonConnection->connectDevice();
|
denonConnection->connectDevice();
|
||||||
return;
|
return;
|
||||||
} else if (thing->thingClassId() == heosThingClassId) {
|
} else if (thing->thingClassId() == heosThingClassId) {
|
||||||
@ -273,48 +288,120 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info)
|
|||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
AvrConnection *avrConnection = m_avrConnections.value(thing->id());
|
AvrConnection *avrConnection = m_avrConnections.value(thing->id());
|
||||||
|
|
||||||
if (action.actionTypeId() == AVRX1000PowerActionTypeId) {
|
if (action.actionTypeId() == AVRX1000PlayActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->play();
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000PauseActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->pause();
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000StopActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->stop();
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000SkipNextActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->skipNext();
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000SkipBackActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->skipBack();
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000PowerActionTypeId) {
|
||||||
bool power = action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool();
|
bool power = action.param(AVRX1000PowerActionPowerParamTypeId).value().toBool();
|
||||||
avrConnection->setPower(power);
|
QUuid commandId = avrConnection->setPower(power);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
} else if (action.actionTypeId() == AVRX1000VolumeActionTypeId) {
|
} else if (action.actionTypeId() == AVRX1000VolumeActionTypeId) {
|
||||||
|
|
||||||
int vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toInt();
|
int vol = action.param(AVRX1000VolumeActionVolumeParamTypeId).value().toInt();
|
||||||
avrConnection->setVolume(vol);
|
QUuid commandId = avrConnection->setVolume(vol);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
} else if (action.actionTypeId() == AVRX1000ChannelActionTypeId) {
|
} else if (action.actionTypeId() == AVRX1000ChannelActionTypeId) {
|
||||||
|
|
||||||
qCDebug(dcDenon) << "Execute update action";
|
|
||||||
QByteArray channel = action.param(AVRX1000ChannelActionChannelParamTypeId).value().toByteArray();
|
QByteArray channel = action.param(AVRX1000ChannelActionChannelParamTypeId).value().toByteArray();
|
||||||
avrConnection->setChannel(channel);
|
QUuid commandId = avrConnection->setChannel(channel);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
} else if (action.actionTypeId() == AVRX1000IncreaseVolumeActionTypeId) {
|
} else if (action.actionTypeId() == AVRX1000IncreaseVolumeActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->increaseVolume();
|
||||||
avrConnection->increaseVolume();
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
|
||||||
} else if (action.actionTypeId() == AVRX1000DecreaseVolumeActionTypeId) {
|
} else if (action.actionTypeId() == AVRX1000DecreaseVolumeActionTypeId) {
|
||||||
|
QUuid commandId = avrConnection->decreaseVolume();
|
||||||
avrConnection->decreaseVolume();
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
|
||||||
} else if (action.actionTypeId() == AVRX1000SurroundModeActionTypeId) {
|
} else if (action.actionTypeId() == AVRX1000SurroundModeActionTypeId) {
|
||||||
|
|
||||||
QByteArray surroundMode = action.param(AVRX1000SurroundModeActionSurroundModeParamTypeId).value().toByteArray();
|
QByteArray surroundMode = action.param(AVRX1000SurroundModeActionSurroundModeParamTypeId).value().toByteArray();
|
||||||
avrConnection->setSurroundMode(surroundMode);
|
QUuid commandId = avrConnection->setSurroundMode(surroundMode);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000MuteActionTypeId) {
|
||||||
|
bool mute = action.param(AVRX1000MuteActionMuteParamTypeId).value().toBool();
|
||||||
|
QUuid commandId = avrConnection->setMute(mute);
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000RepeatActionTypeId) {
|
||||||
|
QString repeatMode = action.param(AVRX1000RepeatActionRepeatParamTypeId).value().toString();
|
||||||
|
QUuid commandId;
|
||||||
|
if (repeatMode == "One") {
|
||||||
|
commandId = avrConnection->setRepeat(AvrConnection::RepeatModeRepeatOne);
|
||||||
|
} else if (repeatMode == "All") {
|
||||||
|
commandId = avrConnection->setRepeat(AvrConnection::RepeatModeRepeatAll);
|
||||||
|
} else {
|
||||||
|
commandId = avrConnection->setRepeat(AvrConnection::RepeatModeRepeatNone);
|
||||||
|
}
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000ShuffleActionTypeId) {
|
||||||
|
bool shuffle = action.param(AVRX1000ShuffleActionShuffleParamTypeId).value().toBool();
|
||||||
|
QUuid commandId = avrConnection->setRandom(shuffle);
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000PlaybackStatusActionTypeId) {
|
||||||
|
QString playbackStatus = action.param(AVRX1000PlaybackStatusActionPlaybackStatusParamTypeId).value().toString();
|
||||||
|
QUuid commandId;
|
||||||
|
if (playbackStatus == "Playing") {
|
||||||
|
commandId = avrConnection->play();
|
||||||
|
} else if (playbackStatus == "Stopped") {
|
||||||
|
commandId = avrConnection->stop();
|
||||||
|
} else if (playbackStatus == "Paused") {
|
||||||
|
commandId = avrConnection->pause();
|
||||||
|
} else {
|
||||||
|
qCWarning(dcDenon()) << "Unrecognized playback status" << playbackStatus;
|
||||||
|
return info->finish(Thing::ThingErrorHardwareFailure, "Unrecognized command");
|
||||||
|
}
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000ToneControlActionTypeId) {
|
||||||
|
bool enable = action.param(AVRX1000ToneControlActionToneControlParamTypeId).value().toBool();
|
||||||
|
QUuid commandId = avrConnection->enableToneControl(enable);
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000BassActionTypeId) {
|
||||||
|
int bass = action.param(AVRX1000BassActionBassParamTypeId).value().toInt();
|
||||||
|
QUuid commandId = avrConnection->setBassLevel(bass);
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else if (action.actionTypeId() == AVRX1000TrebleActionTypeId) {
|
||||||
|
int treble = action.param(AVRX1000TrebleActionTrebleParamTypeId).value().toInt();
|
||||||
|
QUuid commandId = avrConnection->setTrebleLevel(treble);
|
||||||
|
connect(info, &ThingActionInfo::aborted, [this, commandId] {m_avrPendingActions.remove(commandId);});
|
||||||
|
m_avrPendingActions.insert(commandId, info);
|
||||||
|
} else {
|
||||||
|
qCWarning(dcDenon()) << "ActionType not found" << thing->thingClass().name() << action.actionTypeId() ;
|
||||||
|
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||||
}
|
}
|
||||||
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
|
||||||
} else if (thing->thingClassId() == heosThingClassId) {
|
} else if (thing->thingClassId() == heosThingClassId) {
|
||||||
|
|
||||||
Heos *heos = m_heosConnections.value(thing->id());
|
Heos *heos = m_heosConnections.value(thing->id());
|
||||||
if (action.actionTypeId() == heosRebootActionTypeId) {
|
if (action.actionTypeId() == heosRebootActionTypeId) {
|
||||||
heos->rebootSpeaker();
|
heos->rebootSpeaker();
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
return info->finish(Thing::ThingErrorNoError);
|
||||||
|
} else {
|
||||||
|
qCWarning(dcDenon()) << "ActionType not found" << thing->thingClass().name() << action.actionTypeId() ;
|
||||||
|
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||||
}
|
}
|
||||||
} else if (thing->thingClassId() == heosPlayerThingClassId) {
|
} else if (thing->thingClassId() == heosPlayerThingClassId) {
|
||||||
|
|
||||||
@ -369,16 +456,31 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info)
|
|||||||
heos->playNext(playerId);
|
heos->playNext(playerId);
|
||||||
return info->finish(Thing::ThingErrorNoError);
|
return info->finish(Thing::ThingErrorNoError);
|
||||||
} else {
|
} else {
|
||||||
|
qCWarning(dcDenon()) << "ActionType not found" << thing->thingClass().name() << action.actionTypeId() ;
|
||||||
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
qCWarning(dcDenon()) << "ThingClass not found" << thing->thingClass().name() << thing->thingClassId() ;
|
||||||
return info->finish(Thing::ThingErrorThingClassNotFound);
|
return info->finish(Thing::ThingErrorThingClassNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginDenon::postSetupThing(Thing *thing)
|
void IntegrationPluginDenon::postSetupThing(Thing *thing)
|
||||||
{
|
{
|
||||||
if (thing->thingClassId() == heosThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
AvrConnection *avrConnection = m_avrConnections.value(thing->id());
|
||||||
|
thing->setStateValue(AVRX1000ConnectedStateTypeId, avrConnection->connected());
|
||||||
|
avrConnection->getPower();
|
||||||
|
avrConnection->getMute();
|
||||||
|
avrConnection->getVolume();
|
||||||
|
avrConnection->getChannel();
|
||||||
|
avrConnection->getSurroundMode();
|
||||||
|
avrConnection->getPlayBackInfo();
|
||||||
|
avrConnection->getBassLevel();
|
||||||
|
avrConnection->getTrebleLevel();
|
||||||
|
avrConnection->getToneControl();
|
||||||
|
|
||||||
|
} else if (thing->thingClassId() == heosThingClassId) {
|
||||||
Heos *heos = m_heosConnections.value(thing->id());
|
Heos *heos = m_heosConnections.value(thing->id());
|
||||||
thing->setStateValue(heosConnectedStateTypeId, heos->connected());
|
thing->setStateValue(heosConnectedStateTypeId, heos->connected());
|
||||||
if (pluginStorage()->childGroups().contains(thing->id().toString())) {
|
if (pluginStorage()->childGroups().contains(thing->id().toString())) {
|
||||||
@ -414,13 +516,21 @@ void IntegrationPluginDenon::postSetupThing(Thing *thing)
|
|||||||
|
|
||||||
void IntegrationPluginDenon::onPluginTimer()
|
void IntegrationPluginDenon::onPluginTimer()
|
||||||
{
|
{
|
||||||
foreach(AvrConnection *denonConnection, m_avrConnections.values()) {
|
foreach(AvrConnection *avrConnection, m_avrConnections.values()) {
|
||||||
if (!denonConnection->connected()) {
|
if (!avrConnection->connected()) {
|
||||||
denonConnection->connectDevice();
|
avrConnection->connectDevice();
|
||||||
}
|
}
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
Thing *thing = myThings().findById(m_avrConnections.key(avrConnection));
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
denonConnection->getAllStatus();
|
avrConnection->getPower();
|
||||||
|
avrConnection->getMute();
|
||||||
|
avrConnection->getVolume();
|
||||||
|
avrConnection->getChannel();
|
||||||
|
avrConnection->getSurroundMode();
|
||||||
|
avrConnection->getPlayBackInfo();
|
||||||
|
avrConnection->getBassLevel();
|
||||||
|
avrConnection->getTrebleLevel();
|
||||||
|
avrConnection->getToneControl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,19 +547,25 @@ void IntegrationPluginDenon::onPluginTimer()
|
|||||||
void IntegrationPluginDenon::onAvrConnectionChanged(bool status)
|
void IntegrationPluginDenon::onAvrConnectionChanged(bool status)
|
||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
|
||||||
if (!thing)
|
// if the thing and from the first setup
|
||||||
|
if (m_asyncAvrSetups.contains(denonConnection)) {
|
||||||
|
// and ist connected
|
||||||
|
if (status) {
|
||||||
|
ThingSetupInfo *info = m_asyncAvrSetups.take(denonConnection);
|
||||||
|
info->thing()->setStateValue(AVRX1000ConnectedStateTypeId, true);
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing) {
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
// if the thing is connected
|
|
||||||
if (status) {
|
|
||||||
// and from the first setup
|
|
||||||
if (m_asyncAvrSetups.contains(denonConnection)) {
|
|
||||||
ThingSetupInfo *info = m_asyncAvrSetups.take(denonConnection);
|
|
||||||
info->finish(Thing::ThingErrorNoError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thing->setStateValue(AVRX1000ConnectedStateTypeId, denonConnection->connected());
|
thing->setStateValue(AVRX1000ConnectedStateTypeId, denonConnection->connected());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,15 +574,17 @@ void IntegrationPluginDenon::onAvrVolumeChanged(int volume)
|
|||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
if (!thing)
|
if (!thing) {
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
thing->setStateValue(AVRX1000VolumeStateTypeId, volume);
|
thing->setStateValue(AVRX1000VolumeStateTypeId, volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginDenon::onAvrChannelChanged(const QByteArray &channel)
|
void IntegrationPluginDenon::onAvrChannelChanged(const QString &channel)
|
||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
@ -482,8 +600,10 @@ void IntegrationPluginDenon::onAvrMuteChanged(bool mute)
|
|||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
if (!thing)
|
if (!thing) {
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
thing->setStateValue(AVRX1000MuteStateTypeId, mute);
|
thing->setStateValue(AVRX1000MuteStateTypeId, mute);
|
||||||
@ -502,37 +622,157 @@ void IntegrationPluginDenon::onAvrPowerChanged(bool power)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginDenon::onAvrSurroundModeChanged(const QByteArray &surroundMode)
|
void IntegrationPluginDenon::onAvrSurroundModeChanged(const QString &surroundMode)
|
||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
if (!thing)
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
thing->setStateValue(AVRX1000SurroundModeStateTypeId, surroundMode);
|
thing->setStateValue(AVRX1000SurroundModeStateTypeId, surroundMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrSongChanged(const QString &song)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000TitleStateTypeId, song);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrArtistChanged(const QString &artist)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000ArtistStateTypeId, artist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrAlbumChanged(const QString &album)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000CollectionStateTypeId, album);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrBassLevelChanged(int level)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000BassStateTypeId, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrTrebleLevelChanged(int level)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000TrebleStateTypeId, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrToneControlEnabledChanged(bool enabled)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
thing->setStateValue(AVRX1000ToneControlStateTypeId, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntegrationPluginDenon::onAvrPlayBackModeChanged(AvrConnection::PlayBackMode mode)
|
||||||
|
{
|
||||||
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
|
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
||||||
|
if (!thing){
|
||||||
|
qCWarning(dcDenon()) << "Could not find a thing associated to this AVR connection";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
||||||
|
switch (mode) {
|
||||||
|
case AvrConnection::PlayBackModePlaying:
|
||||||
|
thing->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Playing");
|
||||||
|
break;
|
||||||
|
case AvrConnection::PlayBackModePaused:
|
||||||
|
thing->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Paused");
|
||||||
|
break;
|
||||||
|
case AvrConnection::PlayBackModeStopped:
|
||||||
|
thing->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Stopped");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void IntegrationPluginDenon::onAvrSocketError()
|
void IntegrationPluginDenon::onAvrSocketError()
|
||||||
{
|
{
|
||||||
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
|
||||||
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
|
|
||||||
if (!thing)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (thing->thingClassId() == AVRX1000ThingClassId) {
|
// Check if setup running for this thing
|
||||||
|
if (m_asyncAvrSetups.contains(denonConnection)) {
|
||||||
|
ThingSetupInfo *info = m_asyncAvrSetups.take(denonConnection);
|
||||||
|
qCWarning(dcDenon()) << "Could not add thing. The setup failed.";
|
||||||
|
info->finish(Thing::ThingErrorHardwareFailure);
|
||||||
|
// Delete the connection, the thing will not be added and
|
||||||
|
// the connection will be created in the next setup
|
||||||
|
denonConnection->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if setup running for this thing
|
void IntegrationPluginDenon::onAvrCommandExecuted(const QUuid &commandId, bool success)
|
||||||
if (m_asyncAvrSetups.contains(denonConnection)) {
|
{
|
||||||
ThingSetupInfo *info = m_asyncAvrSetups.take(denonConnection);
|
if (m_avrPendingActions.contains(commandId)) {
|
||||||
qCWarning(dcDenon()) << "Could not add thing. The setup failed.";
|
ThingActionInfo *info = m_avrPendingActions.take(commandId);
|
||||||
info->finish(Thing::ThingErrorHardwareFailure);
|
if (success){
|
||||||
// Delete the connection, the thing will not be added and
|
if(info->action().actionTypeId() == AVRX1000PlayActionTypeId) {
|
||||||
// the connection will be created in the next setup
|
info->thing()->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Playing");
|
||||||
denonConnection->deleteLater();
|
} else if(info->action().actionTypeId() == AVRX1000PauseActionTypeId) {
|
||||||
m_avrConnections.remove(thing->id());
|
info->thing()->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Paused");
|
||||||
|
} else if(info->action().actionTypeId() == AVRX1000StopActionTypeId) {
|
||||||
|
info->thing()->setStateValue(AVRX1000PlaybackStatusStateTypeId, "Stopped");
|
||||||
|
} else if(info->action().actionTypeId() == AVRX1000PlaybackStatusActionTypeId) {
|
||||||
|
info->thing()->setStateValue(AVRX1000PlaybackStatusStateTypeId, info->action().param(AVRX1000PlaybackStatusActionPlaybackStatusParamTypeId).value());
|
||||||
|
}
|
||||||
|
info->finish(Thing::ThingErrorNoError);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
info->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,7 +903,7 @@ void IntegrationPluginDenon::onHeosRepeatModeReceived(int playerId, REPEAT_MODE
|
|||||||
void IntegrationPluginDenon::onHeosShuffleModeReceived(int playerId, bool shuffle)
|
void IntegrationPluginDenon::onHeosShuffleModeReceived(int playerId, bool shuffle)
|
||||||
{
|
{
|
||||||
foreach(Thing *thing, myThings().filterByParam(heosPlayerThingPlayerIdParamTypeId, playerId)) {
|
foreach(Thing *thing, myThings().filterByParam(heosPlayerThingPlayerIdParamTypeId, playerId)) {
|
||||||
thing->setStateValue(heosPlayerMuteStateTypeId, shuffle);
|
thing->setStateValue(heosPlayerShuffleStateTypeId, shuffle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,7 +90,8 @@ private:
|
|||||||
QHash<const Action *, int> m_asyncActions;
|
QHash<const Action *, int> m_asyncActions;
|
||||||
QUrl m_notificationUrl;
|
QUrl m_notificationUrl;
|
||||||
|
|
||||||
QHash<int, ThingActionInfo*> m_pendingActions;
|
QHash<int, ThingActionInfo*> m_heosPendingActions;
|
||||||
|
QHash<QUuid, ThingActionInfo*> m_avrPendingActions;
|
||||||
|
|
||||||
QHash<Heos*, BrowseResult*> m_pendingGetSourcesRequest;
|
QHash<Heos*, BrowseResult*> m_pendingGetSourcesRequest;
|
||||||
QHash<QString, BrowseResult*> m_pendingBrowseResult; // QString = containerId or sourceId
|
QHash<QString, BrowseResult*> m_pendingBrowseResult; // QString = containerId or sourceId
|
||||||
@ -128,11 +129,20 @@ private slots:
|
|||||||
|
|
||||||
void onAvrConnectionChanged(bool status);
|
void onAvrConnectionChanged(bool status);
|
||||||
void onAvrSocketError();
|
void onAvrSocketError();
|
||||||
|
void onAvrCommandExecuted(const QUuid &commandId, bool success);
|
||||||
|
|
||||||
void onAvrVolumeChanged(int volume);
|
void onAvrVolumeChanged(int volume);
|
||||||
void onAvrChannelChanged(const QByteArray &channel);
|
void onAvrChannelChanged(const QString &channel);
|
||||||
void onAvrMuteChanged(bool mute);
|
void onAvrMuteChanged(bool mute);
|
||||||
void onAvrPowerChanged(bool power);
|
void onAvrPowerChanged(bool power);
|
||||||
void onAvrSurroundModeChanged(const QByteArray &surroundMode);
|
void onAvrSurroundModeChanged(const QString &surroundMode);
|
||||||
|
void onAvrSongChanged(const QString &song);
|
||||||
|
void onAvrArtistChanged(const QString &artist);
|
||||||
|
void onAvrAlbumChanged(const QString &album);
|
||||||
|
void onAvrPlayBackModeChanged(AvrConnection::PlayBackMode mode);
|
||||||
|
void onAvrBassLevelChanged(int level);
|
||||||
|
void onAvrTrebleLevelChanged(int level);
|
||||||
|
void onAvrToneControlEnabledChanged(bool enabled);
|
||||||
|
|
||||||
void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
void onPluginConfigurationChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
"name": "AVRX1000",
|
"name": "AVRX1000",
|
||||||
"displayName": "AVR X1000",
|
"displayName": "AVR X1000",
|
||||||
"createMethods": ["discovery"],
|
"createMethods": ["discovery"],
|
||||||
"interfaces": ["extendedvolumecontroller", "connectable", "power"],
|
"interfaces": ["mediaplayer", "mediacontroller", "extendedvolumecontroller", "mediametadataprovider", "shufflerepeat", "connectable", "power"],
|
||||||
"paramTypes": [
|
"paramTypes": [
|
||||||
{
|
{
|
||||||
"id": "cb6eeeb0-3d75-43b6-8177-b5ac19648557",
|
"id": "cb6eeeb0-3d75-43b6-8177-b5ac19648557",
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"cached": false
|
"cached": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"displayName": "power",
|
"displayName": "Power",
|
||||||
"id": "1cdb6b54-6831-4900-95b2-c78f64497701",
|
"id": "1cdb6b54-6831-4900-95b2-c78f64497701",
|
||||||
"name": "power",
|
"name": "power",
|
||||||
"displayNameEvent": "Power changed",
|
"displayNameEvent": "Power changed",
|
||||||
@ -80,6 +80,40 @@
|
|||||||
"maxValue": 100,
|
"maxValue": 100,
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Tone control",
|
||||||
|
"id": "d57c1e5e-2cc9-4638-999c-1523f16dbb83",
|
||||||
|
"name": "toneControl",
|
||||||
|
"displayNameEvent": "Tone control changed",
|
||||||
|
"displayNameAction": "Set tone control",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Bass",
|
||||||
|
"id": "2c92b22e-d5b2-4991-a523-64222bffc9e7",
|
||||||
|
"name": "bass",
|
||||||
|
"displayNameEvent": "Bass changed",
|
||||||
|
"displayNameAction": "Set bass",
|
||||||
|
"type": "int",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"minValue": -50,
|
||||||
|
"maxValue": 49,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"displayName": "Treble",
|
||||||
|
"id": "38a3be02-6ed4-4a84-903e-eb923b933989",
|
||||||
|
"name": "treble",
|
||||||
|
"displayNameEvent": "Treble changed",
|
||||||
|
"displayNameAction": "Set treble",
|
||||||
|
"type": "int",
|
||||||
|
"defaultValue": 0,
|
||||||
|
"minValue": -50,
|
||||||
|
"maxValue": 49,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"displayName": "Channel",
|
"displayName": "Channel",
|
||||||
"id": "f29ffa2c-31d6-4d88-b160-a38288c82ce1",
|
"id": "f29ffa2c-31d6-4d88-b160-a38288c82ce1",
|
||||||
@ -136,6 +170,85 @@
|
|||||||
"MATRIX"
|
"MATRIX"
|
||||||
],
|
],
|
||||||
"defaultValue": "MOVIE"
|
"defaultValue": "MOVIE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "50b34df4-90f7-41aa-9a57-6f2d31a18430",
|
||||||
|
"name": "artist",
|
||||||
|
"displayName": "Artist",
|
||||||
|
"displayNameEvent": "Artist changed",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d4f14d93-8cae-4e1b-9ee7-a5c21c0211df",
|
||||||
|
"name": "collection",
|
||||||
|
"displayName": "Album",
|
||||||
|
"displayNameEvent": "Album changed",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d32493d8-5faf-4c7a-ba94-847dc9b81615",
|
||||||
|
"name": "title",
|
||||||
|
"displayName": "Title",
|
||||||
|
"displayNameEvent": "Title changed",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6c4a208b-5b04-40cc-b14b-8f79aff30307",
|
||||||
|
"name": "artwork",
|
||||||
|
"displayName": "Artwork",
|
||||||
|
"displayNameEvent": "Artwork changed",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2f372374-16f3-4900-afdc-834f51075d07",
|
||||||
|
"name": "playerType",
|
||||||
|
"displayName": "Player type",
|
||||||
|
"displayNameEvent": "Player type changed",
|
||||||
|
"possibleValues": [
|
||||||
|
"audio",
|
||||||
|
"video"
|
||||||
|
],
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": "audio"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8ef6708c-812a-4e6a-a608-9e480aa3b7bf",
|
||||||
|
"name": "playbackStatus",
|
||||||
|
"displayName": "Playback status",
|
||||||
|
"displayNameEvent": "Playback status changed",
|
||||||
|
"displayNameAction": "Set playback status",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": "Stopped",
|
||||||
|
"possibleValues": ["Playing", "Paused", "Stopped"],
|
||||||
|
"cached": false,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8ad33cb9-e758-433d-a013-2e4d43157c92",
|
||||||
|
"name": "shuffle",
|
||||||
|
"displayName": "Shuffle",
|
||||||
|
"displayNameEvent": "Shuffle changed",
|
||||||
|
"displayNameAction": "Set shuffle",
|
||||||
|
"type": "bool",
|
||||||
|
"defaultValue": false,
|
||||||
|
"cached": false,
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9478987b-14e4-4572-a059-a18a5a9db229",
|
||||||
|
"name": "repeat",
|
||||||
|
"displayName": "Repeat mode",
|
||||||
|
"displayNameEvent": "Repeat mode changed",
|
||||||
|
"displayNameAction": "Set repeat mode",
|
||||||
|
"type": "QString",
|
||||||
|
"defaultValue": "None",
|
||||||
|
"possibleValues": ["None", "One", "All"],
|
||||||
|
"cached": false,
|
||||||
|
"writable": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actionTypes": [
|
"actionTypes": [
|
||||||
@ -164,6 +277,31 @@
|
|||||||
"type": "int"
|
"type": "int"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3f2eb789-918c-475a-a295-14c0c24338b8",
|
||||||
|
"name": "skipBack",
|
||||||
|
"displayName": "Skip back"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ddab0869-5b90-4fd4-9c40-9ad57101b87c",
|
||||||
|
"name": "stop",
|
||||||
|
"displayName": "Stop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d04eb30b-838d-4fbd-b781-c01005b59756",
|
||||||
|
"name": "play",
|
||||||
|
"displayName": "Play"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3de38047-006f-4d97-9326-08bb5ad79b05",
|
||||||
|
"name": "pause",
|
||||||
|
"displayName": "Pause"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bf9664e4-a53e-474c-afcc-88f25e6fe365",
|
||||||
|
"name": "skipNext",
|
||||||
|
"displayName": "Skip next"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user