From 8fa10cc548b4df67ea7e43616cd19c1d343ff40c Mon Sep 17 00:00:00 2001 From: Boernsman Date: Thu, 6 Feb 2020 14:55:08 +0500 Subject: [PATCH] playing favorites do work now --- denon/heos.cpp | 93 +++++++++++--- denon/heos.h | 25 ++-- denon/integrationplugindenon.cpp | 193 ++++++++++++++++++++++++++++-- denon/integrationplugindenon.h | 27 ++++- denon/integrationplugindenon.json | 19 ++- 5 files changed, 315 insertions(+), 42 deletions(-) diff --git a/denon/heos.cpp b/denon/heos.cpp index fd3a6447..a0a34724 100644 --- a/denon/heos.cpp +++ b/denon/heos.cpp @@ -35,6 +35,7 @@ #include #include #include +#include Heos::Heos(const QHostAddress &hostAddress, QObject *parent) : QObject(parent), @@ -383,26 +384,36 @@ void Heos::groupVolumeDown(int groupId, int step) /******************************** * BROWSE COMMANDS ********************************/ -void Heos::getMusicSources() +quint32 Heos::getMusicSources() { - QByteArray cmd = "heos://browse/get_music_sources\r\n"; + quint32 sequence = QRandomGenerator::global()->generate(); + QByteArray cmd = "heos://browse/get_music_sources?"; + QUrlQuery queryParams; + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); + cmd.append(queryParams.toString()); + cmd.append("\r\n"); qCDebug(dcDenon) << "Get music sources:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::getSourceInfo(const QString &sourceId) +quint32 Heos::getSourceInfo(const QString &sourceId) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd = "heos://browse/get_source_info?"; QUrlQuery queryParams; queryParams.addQueryItem("sid", sourceId); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "Get source info:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::getSearchCriteria(const QString &sourceId) +quint32 Heos::getSearchCriteria(const QString &sourceId) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd = "heos://browse/get_search_criteria?"; QUrlQuery queryParams; queryParams.addQueryItem("sid", sourceId); @@ -410,94 +421,118 @@ void Heos::getSearchCriteria(const QString &sourceId) cmd.append("\r\n"); qCDebug(dcDenon) << "Get search criteria:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::browseSource(const QString &sourceId) +quint32 Heos::browseSource(const QString &sourceId) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd = "heos://browse/browse?"; QUrlQuery queryParams; queryParams.addQueryItem("sid", sourceId); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "Browse source:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::browseSourceContainers(const QString &sourceId, const QString &containerId) +quint32 Heos::browseSourceContainers(const QString &sourceId, const QString &containerId) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd = "heos://browse/browse?"; QUrlQuery queryParams; queryParams.addQueryItem("sid", sourceId); queryParams.addQueryItem("cid", containerId); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "Browsing container:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::playStation(int playerId, const QString &sourceId, const QString &containerId, const QString &mediaId, const QString &stationName) +quint32 Heos::playStation(int playerId, const QString &sourceId, const QString &containerId, const QString &mediaId, const QString &stationName) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd("heos://browse/play_stream?"); QUrlQuery queryParams; queryParams.addQueryItem("pid", QString::number(playerId)); queryParams.addQueryItem("sid", sourceId); - queryParams.addQueryItem("cid", containerId); + if (!containerId.isEmpty()) { + queryParams.addQueryItem("cid", containerId); + } queryParams.addQueryItem("mid", mediaId); queryParams.addQueryItem("name", stationName); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "playing station:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::playPresetStation(int playerId, int presetNumber) +quint32 Heos::playPresetStation(int playerId, int presetNumber) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd("heos://browse/play_preset?"); QUrlQuery queryParams; queryParams.addQueryItem("pid", QString::number(playerId)); queryParams.addQueryItem("preset", QString::number(presetNumber)); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "playing preset station:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::playInputSource(int playerId, const QString &inputName) +quint32 Heos::playInputSource(int playerId, const QString &inputName) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd("heos://browse/play_input?"); QUrlQuery queryParams; queryParams.addQueryItem("pid", QString::number(playerId)); queryParams.addQueryItem("input", inputName); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "playing input source:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::playUrl(int playerId, const QUrl &mediaUrl) +quint32 Heos::playUrl(int playerId, const QUrl &mediaUrl) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd("heos://browse/play_stream?"); QUrlQuery queryParams; queryParams.addQueryItem("pid", QString::number(playerId)); queryParams.addQueryItem("url", mediaUrl.toString()); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "playing url:" << cmd; m_socket->write(cmd); + return sequence; } -void Heos::addContainerToQueue(int playerId, const QString &sourceId, const QString &containerId, ADD_CRITERIA addCriteria) +quint32 Heos::addContainerToQueue(int playerId, const QString &sourceId, const QString &containerId, ADD_CRITERIA addCriteria) { + quint32 sequence = QRandomGenerator::global()->generate(); QByteArray cmd("heos://browse/add_to_queue?"); QUrlQuery queryParams; queryParams.addQueryItem("pid", QString::number(playerId)); queryParams.addQueryItem("sid", sourceId); queryParams.addQueryItem("cid", containerId); queryParams.addQueryItem("aid", QString::number(addCriteria)); + queryParams.addQueryItem("SEQUENCE", QString::number(sequence)); cmd.append(queryParams.toString()); cmd.append("\r\n"); qCDebug(dcDenon) << "Adding to queue:" << cmd; m_socket->write(cmd); + return sequence; } void Heos::onConnected() @@ -569,10 +604,31 @@ void Heos::readData() } else if (command.contains("check_account")) { + qDebug(dcDenon()) << "System command check_account:" << message.toString(); + bool signedIn; + QString username = ""; + if (message.hasQueryItem("signed_in")){ + signedIn = true; + username = message.queryItemValue("un"); + } else { + signedIn = false; + } + emit userChanged(signedIn, username); + } else if (command.contains("sign_in")) { + qDebug(dcDenon()) << "System command sign_in:" << message.toString(); + + if (message.hasQueryItem("signed_in")) { + bool signedIn = true; + QString username = message.queryItemValue("un"); + emit userChanged(signedIn, username); + } // otherwise it will be command under process and we will wait for the event } else if (command.contains("sign_out")) { + qDebug(dcDenon()) << "System command sign_out:" << message.toString(); + emit userChanged(false, ""); + } else if (command.contains("heart_beat")) { } else if (command.contains("reboot")) { @@ -817,6 +873,12 @@ void Heos::readData() */ } else if (command.startsWith("browse") || command.startsWith(" browse")) { + quint32 sequenceNumber = 0; + if (message.hasQueryItem("SEQUENCE")) { + qDebug(dcDenon) << "Sequence number" << message.queryItemValue("SEQUENCE"); + sequenceNumber = message.queryItemValue("SEQUENCE").toUInt(); + } + if (command.contains("get_music_sources") || command.contains("get_source_info")) { qDebug(dcDenon()) << "Get music source request response received" << command; QVariantList payloadVariantList = jsonDoc.toVariant().toMap().value("payload").toList(); @@ -832,10 +894,11 @@ void Heos::readData() source.serviceUsername = payloadEntryVariant.toMap().value("service_username").toString(); musicSources.append(source); } - emit musicSourcesReceived(musicSources); + emit musicSourcesReceived(sequenceNumber, musicSources); } } else if (command.contains("browse/browse")) { + qDebug(dcDenon()) << "Browse response:" << jsonDoc.toVariant().toMap().value("payload"); QVariantList payloadVariantList = jsonDoc.toVariant().toMap().value("payload").toList(); QString sourceId = message.queryItemValue("sid"); QString containerId = message.queryItemValue("cid"); @@ -889,7 +952,7 @@ void Heos::readData() mediaItems.append(media); } } - emit browseRequestReceived(sourceId, containerId, musicSources, mediaItems); + emit browseRequestReceived(sequenceNumber, sourceId, containerId, musicSources, mediaItems); } else { int errorId = message.queryItemValue("eid").toInt(); @@ -1059,7 +1122,7 @@ void Heos::readData() } } else if (command.contains("user_changed")) { - qDebug(dcDenon()) << "Event user changed"; + qDebug(dcDenon()) << "Event user changed" << message.toString(); bool signedIn; QString username; if (message.hasQueryItem("signed_out")){ diff --git a/denon/heos.h b/denon/heos.h index 617ea9bf..e9c2d737 100644 --- a/denon/heos.h +++ b/denon/heos.h @@ -106,18 +106,19 @@ public: void groupVolumeDown(int groupId, int step = 5); //Browse Get Commands - void getMusicSources(); - void getSourceInfo(const QString &sourceId); - void getSearchCriteria(const QString &sourceId); - void browseSource(const QString &sourceId); - void browseSourceContainers(const QString &sourceId, const QString &containerId); + quint32 getMusicSources(); + quint32 getSourceInfo(const QString &sourceId); + quint32 getSearchCriteria(const QString &sourceId); + quint32 browseSource(const QString &sourceId); + quint32 browseSourceContainers(const QString &sourceId, const QString &containerId); + quint32 addContainerToQueue(int playerId, const QString &sourceId, const QString &containerId, ADD_CRITERIA addCriteria); + // Controllers can add custom argument SEQUENCE= in browse commands to associate command and response. //Play commands - void playStation(int playerId, const QString &sourceId, const QString &containerId, const QString &mediaId, const QString &stationName); - void playPresetStation(int playerId, int presetNumber); - void playInputSource(int playerId, const QString &inputName); //Validity of Inputs depends on the type of source HEOS devic - void playUrl(int playerId, const QUrl &url); - void addContainerToQueue(int playerId, const QString &sourceId, const QString &containerId, ADD_CRITERIA addCriteria); + quint32 playStation(int playerId, const QString &sourceId, const QString &containerId, const QString &mediaId, const QString &stationName); + quint32 playPresetStation(int playerId, int presetNumber); + quint32 playInputSource(int playerId, const QString &inputName); //Validity of Inputs depends on the type of source HEOS devie + quint32 playUrl(int playerId, const QUrl &url); private: bool m_eventRegistered = false; @@ -155,8 +156,8 @@ signals: void sourcesChanged(); void nowPlayingMediaStatusReceived(int playerId, const QString &sourceId, const QString &artist, const QString &album, const QString &song, const QString &artwork); - void musicSourcesReceived(QList musicSources); //callback of getMusicSource, not associated to a playerId - void browseRequestReceived(const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems); //callback of browseSource + void musicSourcesReceived(quint32 sequenceNumber, QList musicSources); //callback of getMusicSource, not associated to a playerId + void browseRequestReceived(quint32 sequenceNumber, const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems); //callback of browseSource void browseErrorReceived(const QString &sourceId, const QString &containerId, int errorId, const QString &errorMessage); void userChanged(bool signedIn, const QString &userName); diff --git a/denon/integrationplugindenon.cpp b/denon/integrationplugindenon.cpp index d447eeba..d3134f39 100644 --- a/denon/integrationplugindenon.cpp +++ b/denon/integrationplugindenon.cpp @@ -167,7 +167,43 @@ void IntegrationPluginDenon::discoverThings(ThingDiscoveryInfo *info) >>>>>>> tryna to fix discovery:denon/deviceplugindenon.cpp } +<<<<<<< HEAD:denon/integrationplugindenon.cpp void IntegrationPluginDenon::setupThing(ThingSetupInfo *info) +======= +void DevicePluginDenon::startPairing(DevicePairingInfo *info) +{ + info->finish(Device::DeviceErrorNoError, QT_TR_NOOP("Please enter your HEOS account credentials. Leave empty if you doesn't have any. Some features like music browsing won't be available.")); +} + +void DevicePluginDenon::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &password) +{ + + if (info->deviceClassId() == heosDeviceClassId) { + + if (username.isEmpty()) { //device connection will be setup without an user account + info->finish(Device::DeviceErrorNoError); + } + + QHostAddress address(info->params().paramValue(heosDeviceIpParamTypeId).toString()); + Heos *heos = createHeosConnection(address); + m_unfinishedHeosConnections.insert(info->deviceId(), heos); + m_unfinishedHeosPairings.insert(heos, info); + connect(info, &DevicePairingInfo::aborted, this, [heos, this] { + m_unfinishedHeosPairings.remove(heos); + heos->deleteLater(); + }); + heos->connectDevice(); + heos->setUserAccount(username, password);; + + pluginStorage()->beginGroup(info->deviceId().toString()); + pluginStorage()->setValue("username", username); + pluginStorage()->setValue("password", password); + pluginStorage()->endGroup(); + } +} + +void DevicePluginDenon::setupDevice(DeviceSetupInfo *info) +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp { Thing *thing = info->thing(); @@ -195,7 +231,7 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info) m_asyncAvrSetups.insert(denonConnection, info); // In case the setup is cancelled before we finish it... - connect(info, &QObject::destroyed, this, [this, info, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); }); + connect(info, &QObject::destroyed, this, [this, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); }); denonConnection->connectDevice(); return; @@ -210,6 +246,7 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info) return; } +<<<<<<< HEAD:denon/integrationplugindenon.cpp Heos *heos = new Heos(address, this); connect(heos, &Heos::connectionStatusChanged, this, &IntegrationPluginDenon::onHeosConnectionChanged); connect(heos, &Heos::playersChanged, this, &IntegrationPluginDenon::onHeosPlayersChanged); @@ -234,16 +271,46 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info) m_asyncHeosSetups.insert(heos, info); // In case the setup is cancelled before we finish it... connect(info, &QObject::destroyed, this, [this, info, heos]() { m_asyncHeosSetups.remove(heos); }); +======= + Heos *heos; + if (m_unfinishedHeosConnections.contains(device->id())) { + heos = m_unfinishedHeosConnections.take(device->id()); + info->finish(Device::DeviceErrorNoError); + } else { + heos = createHeosConnection(address); + m_asyncHeosSetups.insert(heos, info); + // In case the setup is cancelled before we finish it... + connect(info, &QObject::destroyed, this, [this, heos]() { m_asyncHeosSetups.remove(heos); }); + heos->connectDevice(); + pluginStorage()->beginGroup(device->id().toString()); + if (pluginStorage()->contains("username")) { + QString username = pluginStorage()->value("username").toString(); + QString password = pluginStorage()->value("password").toString(); + heos->setUserAccount(username, password); + } + pluginStorage()->endGroup(); + } + m_heosConnections.insert(device->id(), heos); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp - heos->connectDevice(); return; +<<<<<<< HEAD:denon/integrationplugindenon.cpp } if (thing->thingClassId() == heosPlayerThingClassId) { info->finish(Thing::ThingErrorNoError); +======= + } else if (device->deviceClassId() == heosPlayerDeviceClassId) { + info->finish(Device::DeviceErrorNoError); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp return; + } else { + info->finish(Device::DeviceErrorDeviceClassNotFound); } +<<<<<<< HEAD:denon/integrationplugindenon.cpp info->finish(Thing::ThingErrorThingClassNotFound); +======= +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp } void IntegrationPluginDenon::thingRemoved(Thing *thing) @@ -258,11 +325,19 @@ void IntegrationPluginDenon::thingRemoved(Thing *thing) denonConnection->disconnectDevice(); denonConnection->deleteLater(); } +<<<<<<< HEAD:denon/integrationplugindenon.cpp } else if (thing->thingClassId() == heosThingClassId) { if (m_heos.contains(thing->id())) { Heos *heos = m_heos.take(thing->id()); +======= + } else if (device->deviceClassId() == heosDeviceClassId) { + if (m_heosConnections.contains(device->id())) { + Heos *heos = m_heosConnections.take(device->id()); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp heos->deleteLater(); } + + pluginStorage()->remove(device->id().toString()); } if (myThings().empty()) { @@ -325,9 +400,15 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info) } else if (device->deviceClassId() == heosPlayerDeviceClassId) { >>>>>>> tryna to fix discovery:denon/deviceplugindenon.cpp +<<<<<<< HEAD:denon/integrationplugindenon.cpp Thing *heosThing = myThings().findById(thing->parentId()); Heos *heos = m_heos.value(heosThing->id()); int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt(); +======= + Device *heosDevice = myDevices().findById(device->parentId()); + Heos *heos = m_heosConnections.value(heosDevice->id()); + int playerId = device->paramValue(heosPlayerDevicePlayerIdParamTypeId).toInt(); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp if (action.actionTypeId() == heosPlayerAlertActionTypeId) { heos->playUrl(playerId, m_notificationUrl); @@ -438,8 +519,13 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info) void IntegrationPluginDenon::postSetupThing(Thing *thing) { +<<<<<<< HEAD:denon/integrationplugindenon.cpp if (thing->thingClassId() == heosThingClassId) { Heos *heos = m_heos.value(thing->id()); +======= + if (device->deviceClassId() == heosDeviceClassId) { + Heos *heos = m_heosConnections.value(device->id()); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp device->setStateValue(heosConnectedStateTypeId, heos->connected()); heos->getPlayers(); heos->getGroups(); @@ -456,7 +542,7 @@ void IntegrationPluginDenon::postSetupThing(Thing *thing) } else if (device->deviceClassId() == heosPlayerDeviceClassId) { device->setStateValue(heosPlayerConnectedStateTypeId, true); Device *heosDevice = myDevices().findById(device->parentId()); - Heos *heos = m_heos.value(heosDevice->id()); + Heos *heos = m_heosConnections.value(heosDevice->id()); int playerId = device->paramValue(heosPlayerDevicePlayerIdParamTypeId).toInt(); >>>>>>> tryna to fix discovery:denon/deviceplugindenon.cpp heos->getPlayerState(playerId); @@ -488,8 +574,13 @@ void IntegrationPluginDenon::onPluginTimer() foreach(Thing *thing, myThings()) { +<<<<<<< HEAD:denon/integrationplugindenon.cpp if (thing->thingClassId() == heosThingClassId) { Heos *heos = m_heos.value(thing->id()); +======= + if (device->deviceClassId() == heosDeviceClassId) { + Heos *heos = m_heosConnections.value(device->id()); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp heos->getPlayers(); heos->registerForChangeEvents(true); <<<<<<< HEAD:denon/integrationplugindenon.cpp @@ -502,10 +593,11 @@ void IntegrationPluginDenon::onPluginTimer() ======= } else if (device->deviceClassId() == heosPlayerDeviceClassId) { Device *heosDevice = myDevices().findById(device->parentId()); - Heos *heos = m_heos.value(heosDevice->id()); + Heos *heos = m_heosConnections.value(heosDevice->id()); int playerId = device->paramValue(heosPlayerDevicePlayerIdParamTypeId).toInt(); >>>>>>> tryna to fix discovery:denon/deviceplugindenon.cpp + //TODO check if event stream is sufficent and remove polling heos->getPlayerState(playerId); heos->getPlayMode(playerId); heos->getVolume(playerId); @@ -647,14 +739,14 @@ void IntegrationPluginDenon::onHeosConnectionChanged(bool status) thing->setStateValue(heosConnectedStateTypeId, status); ======= if (status) { - // and from the first setup + if (m_asyncHeosSetups.contains(heos)) { DeviceSetupInfo *info = m_asyncHeosSetups.take(heos); info->finish(Device::DeviceErrorNoError); } } - Device *device = myDevices().findById(m_heos.key(heos)); + Device *device = myDevices().findById(m_heosConnections.key(heos)); if (!device) return; @@ -663,11 +755,17 @@ void IntegrationPluginDenon::onHeosConnectionChanged(bool status) device->setStateValue(heosConnectedStateTypeId, status); >>>>>>> added join/unjoin group:denon/IntegrationPlugindenon.cpp // update connection status for all child devices +<<<<<<< HEAD:denon/integrationplugindenon.cpp foreach (Thing *playerDevice, myThings()) { if (playerDevice->thingClassId() == heosPlayerThingClassId) { if (playerDevice->parentId() == thing->id()) { playerDevice->setStateValue(heosPlayerConnectedStateTypeId, status); } +======= + foreach (Device *playerDevice, myDevices().filterByParentDeviceId(device->id())) { + if (playerDevice->deviceClassId() == heosPlayerDeviceClassId) { + playerDevice->setStateValue(heosPlayerConnectedStateTypeId, status); +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp } } } @@ -686,6 +784,13 @@ void IntegrationPluginDenon::onHeosPlayersReceived(QList heosPlaye >>>>>>> added join/unjoin group:denon/IntegrationPlugindenon.cpp Heos *heos = static_cast(sender()); +<<<<<<< HEAD:denon/integrationplugindenon.cpp +======= + Device *device = myDevices().findById(m_heosConnections.key(heos)); + if (!device) { + return; + } +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp <<<<<<< HEAD:denon/integrationplugindenon.cpp Thing *thing = myThings().findById(m_heos.key(heos)); @@ -729,6 +834,7 @@ void IntegrationPluginDenon::onHeosPlayStateReceived(int playerId, PLAYER_STATE ======= //TODO remove devices + //autoDeviceDisappeared(); //TODO remove player from player Buffer autoDevicesAppeared(heosPlayerDescriptors); } @@ -891,9 +997,14 @@ void IntegrationPluginDenon::onHeosNowPlayingMediaStatusReceived(int playerId, c >>>>>>> added join/unjoin group:denon/IntegrationPlugindenon.cpp } +<<<<<<< HEAD:denon/integrationplugindenon.cpp void IntegrationPluginDenon::onHeosMusicSourcesReceived(QList musicSources) +======= +void DevicePluginDenon::onHeosMusicSourcesReceived(quint32 sequenceNumber, QList musicSources) +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp { + Q_UNUSED(sequenceNumber) Heos *heos = static_cast(sender()); if (m_pendingGetSourcesRequest.contains(heos)) { BrowseResult *result = m_pendingGetSourcesRequest.take(heos); @@ -902,7 +1013,12 @@ void IntegrationPluginDenon::onHeosMusicSourcesReceived(QList item.setDisplayName(source.name); item.setId("source=" + QString::number(source.sourceId)); item.setExecutable(false); - item.setBrowsable(true); + item.setBrowsable(source.available); + if (!source.available) { + item.setDescription(tr("Service is not available")); + } else { + item.setDescription(source.serviceUsername); + } item.setIcon(BrowserItem::BrowserIconMusic); if (source.name == "Amazon") { item.setMediaIcon(MediaBrowserItem::MediaBrowserIconAmazon); @@ -936,10 +1052,15 @@ void IntegrationPluginDenon::onHeosMusicSourcesReceived(QList } } +<<<<<<< HEAD:denon/integrationplugindenon.cpp void IntegrationPluginDenon::onHeosMediaItemsReceived(QList mediaItems) void IntegrationPluginDenon::onHeosBrowseRequestReceived(const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems) +======= +void DevicePluginDenon::onHeosBrowseRequestReceived(quint32 sequenceNumber, const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems) +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp { + Q_UNUSED(sequenceNumber) QString identifier; if (containerId.isEmpty()) { identifier = sourceId; @@ -1062,8 +1183,34 @@ void IntegrationPluginDenon::onHeosGroupsChanged() heos->getPlayers(); } +<<<<<<< HEAD:denon/integrationplugindenon.cpp void IntegrationPluginDenon::onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry) >>>>>>> added join/unjoin group:denon/IntegrationPlugindenon.cpp +======= +void DevicePluginDenon::onHeosUserChanged(bool signedIn, const QString &userName) +{ + Q_UNUSED(userName) + Heos *heos = static_cast(sender()); + if (m_unfinishedHeosPairings.contains(heos)) { + DevicePairingInfo *info = m_unfinishedHeosPairings.take(heos); + if (signedIn) { + info->finish(Device::DeviceErrorNoError); + } else { + info->finish(Device::DeviceErrorAuthenticationFailure, tr("Wrong username or password")); + m_unfinishedHeosConnections.remove(info->deviceId()); + heos->deleteLater(); + } + } + + if (m_heosConnections.values().contains(heos)) { + Device *device = myDevices().findById(m_heosConnections.key(heos)); + device->setStateValue(heosLoggedInStateTypeId, signedIn); + device->setStateValue(heosUserDisplayNameStateTypeId, userName); + } +} + +void DevicePluginDenon::onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry) +>>>>>>> playing favorites do work now:denon/deviceplugindenon.cpp { qCDebug(dcDenon()) << "Avahi service entry added:" << serviceEntry; } @@ -1087,7 +1234,7 @@ void IntegrationPluginDenon::onPluginConfigurationChanged(const ParamTypeId &par void IntegrationPluginDenon::browseDevice(BrowseResult *result) { - Heos *heos = m_heos.value(result->device()->parentId()); + Heos *heos = m_heosConnections.value(result->device()->parentId()); if (!heos) { result->finish(Device::DeviceErrorHardwareNotAvailable); return; @@ -1179,7 +1326,7 @@ void IntegrationPluginDenon::browseDevice(BrowseResult *result) void IntegrationPluginDenon::browserItem(BrowserItemResult *result) { - Heos *heos = m_heos.value(result->device()->parentId()); + Heos *heos = m_heosConnections.value(result->device()->parentId()); if (!heos) { result->finish(Device::DeviceErrorHardwareNotAvailable); return; @@ -1190,7 +1337,7 @@ void IntegrationPluginDenon::browserItem(BrowserItemResult *result) void IntegrationPluginDenon::executeBrowserItem(BrowserActionInfo *info) { - Heos *heos = m_heos.value(info->device()->parentId()); + Heos *heos = m_heosConnections.value(info->device()->parentId()); if (!heos) { info->finish(Device::DeviceErrorHardwareNotAvailable); return; @@ -1216,7 +1363,7 @@ void IntegrationPluginDenon::executeBrowserItem(BrowserActionInfo *info) void IntegrationPluginDenon::executeBrowserItemAction(BrowserItemActionInfo *info) { - Heos *heos = m_heos.value(info->device()->parentId()); + Heos *heos = m_heosConnections.value(info->device()->parentId()); if (!heos) { info->finish(Device::DeviceErrorHardwareNotAvailable); return; @@ -1254,3 +1401,27 @@ void IntegrationPluginDenon::executeBrowserItemAction(BrowserItemActionInfo *inf info->finish(Device::DeviceErrorNoError); return; } + +Heos *DevicePluginDenon::createHeosConnection(const QHostAddress &address) +{ + Heos *heos = new Heos(address, this); + connect(heos, &Heos::connectionStatusChanged, this, &DevicePluginDenon::onHeosConnectionChanged); + connect(heos, &Heos::playersChanged, this, &DevicePluginDenon::onHeosPlayersChanged); + connect(heos, &Heos::playersRecieved, this, &DevicePluginDenon::onHeosPlayersReceived); + connect(heos, &Heos::playerInfoRecieved, this, &DevicePluginDenon::onHeosPlayerInfoRecieved); + connect(heos, &Heos::playerPlayStateReceived, this, &DevicePluginDenon::onHeosPlayStateReceived); + connect(heos, &Heos::playerRepeatModeReceived, this, &DevicePluginDenon::onHeosRepeatModeReceived); + connect(heos, &Heos::playerShuffleModeReceived, this, &DevicePluginDenon::onHeosShuffleModeReceived); + connect(heos, &Heos::playerMuteStatusReceived, this, &DevicePluginDenon::onHeosMuteStatusReceived); + connect(heos, &Heos::playerVolumeReceived, this, &DevicePluginDenon::onHeosVolumeStatusReceived); + connect(heos, &Heos::nowPlayingMediaStatusReceived, this, &DevicePluginDenon::onHeosNowPlayingMediaStatusReceived); + connect(heos, &Heos::playerNowPlayingChanged, this, &DevicePluginDenon::onHeosPlayerNowPlayingChanged); + connect(heos, &Heos::musicSourcesReceived, this, &DevicePluginDenon::onHeosMusicSourcesReceived); + connect(heos, &Heos::browseRequestReceived, this, &DevicePluginDenon::onHeosBrowseRequestReceived); + connect(heos, &Heos::browseErrorReceived, this, &DevicePluginDenon::onHeosBrowseErrorReceived); + connect(heos, &Heos::playerQueueChanged, this, &DevicePluginDenon::onHeosPlayerQueueChanged); + connect(heos, &Heos::groupsReceived, this, &DevicePluginDenon::onHeosGroupsReceived); + connect(heos, &Heos::groupsChanged, this, &DevicePluginDenon::onHeosGroupsChanged); + connect(heos, &Heos::userChanged, this, &DevicePluginDenon::onHeosUserChanged); + return heos; +} diff --git a/denon/integrationplugindenon.h b/denon/integrationplugindenon.h index a2205ae9..12811258 100644 --- a/denon/integrationplugindenon.h +++ b/denon/integrationplugindenon.h @@ -57,12 +57,24 @@ class IntegrationPluginDenon : public IntegrationPlugin public: explicit IntegrationPluginDenon(); +<<<<<<< HEAD:denon/integrationplugindenon.h void init() override; void discoverThings(ThingDiscoveryInfo *info) override; void setupThing(ThingSetupInfo *info) override; void postSetupThing(Thing *thing) override; void executeAction(ThingActionInfo *info) override; void thingRemoved(Thing *thing) override; +======= + void discoverDevices(DeviceDiscoveryInfo *info) override; + + void startPairing(DevicePairingInfo *info) override; + void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) override; + + void setupDevice(DeviceSetupInfo *info) override; + void postSetupDevice(Device *device) override; + void executeAction(DeviceActionInfo *info) override; + void deviceRemoved(Device *device) override; +>>>>>>> playing favorites do work now:denon/deviceplugindenon.h void browseThing(BrowseResult *result) override; void browserItem(BrowserItemResult *result) override; @@ -73,8 +85,15 @@ private: PluginTimer *m_pluginTimer = nullptr; ZeroConfServiceBrowser *m_serviceBrowser = nullptr; +<<<<<<< HEAD:denon/integrationplugindenon.h QHash m_avrConnections; QHash m_heos; +======= + QHash m_avrConnections; + QHash m_heosConnections; + QHash m_unfinishedHeosConnections; + QHash m_unfinishedHeosPairings; +>>>>>>> playing favorites do work now:denon/deviceplugindenon.h QHash m_asyncAvrSetups; QHash m_asyncHeosSetups; @@ -94,6 +113,8 @@ private: QHash m_groupBuffer; QHash m_playerBuffer; + Heos *createHeosConnection(const QHostAddress &address); + private slots: void onPluginTimer(); @@ -107,15 +128,15 @@ private slots: void onHeosMuteStatusReceived(int playerId, bool mute); void onHeosVolumeStatusReceived(int playerId, int volume); void onHeosNowPlayingMediaStatusReceived(int playerId, const QString &sourceId, const QString &artist, const QString &album, const QString &song, const QString &artwork); - void onHeosMusicSourcesReceived(QList musicSources); + void onHeosMusicSourcesReceived(quint32 sequenceNumber, QList musicSources); - void onHeosBrowseRequestReceived(const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems); + void onHeosBrowseRequestReceived(quint32 sequenceNumber, const QString &sourceId, const QString &containerId, QList musicSources, QList mediaItems); void onHeosBrowseErrorReceived(const QString &sourceId, const QString &containerId, int errorId, const QString &errorMessage); void onHeosPlayerNowPlayingChanged(int playerId); void onHeosPlayerQueueChanged(int playerId); void onHeosGroupsReceived(QList groups); void onHeosGroupsChanged(); - + void onHeosUserChanged(bool signedIn, const QString &userName); void onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry); void onAvahiServiceEntryRemoved(const ZeroConfServiceEntry &serviceEntry); diff --git a/denon/integrationplugindenon.json b/denon/integrationplugindenon.json index fd5d3e31..cc9c40cd 100644 --- a/denon/integrationplugindenon.json +++ b/denon/integrationplugindenon.json @@ -171,6 +171,7 @@ "name": "heos", "displayName": "Heos", "createMethods": ["discovery"], + "setupMethod": "userandpassword", "interfaces": ["gateway"], "paramTypes": [ { @@ -201,6 +202,22 @@ "displayNameEvent": "Connected changed", "defaultValue": false, "type": "bool" + }, + { + "id": "ab689a6e-eb71-4a41-a267-ba1afe7e2f56", + "name": "loggedIn", + "displayName": "Logged in", + "displayNameEvent": "Logged in changed", + "defaultValue": true, + "type": "bool" + }, + { + "id": "77756132-5fa4-409e-969e-d23bcee72356", + "name": "userDisplayName", + "displayName": "User name", + "displayNameEvent": "User name changed", + "type": "QString", + "defaultValue": "" } ] }, @@ -367,7 +384,7 @@ { "id": "a718f7e9-0b54-4403-b661-49f7b0d13085", "name": "skipBack", - "displayName": "Akip back" + "displayName": "Skip back" }, { "id": "c4b29c09-e3b3-4843-b6d9-e032f3fc1d78",