added browsing function

This commit is contained in:
nymea 2019-09-30 21:23:22 +02:00 committed by bernhard.trinnes
parent 79774e5c67
commit 8a154af241
5 changed files with 197 additions and 52 deletions

View File

@ -363,21 +363,33 @@ void Heos::getMusicSources()
void Heos::getSourceInfo(SOURCE_ID sourceId) void Heos::getSourceInfo(SOURCE_ID sourceId)
{ {
QByteArray cmd = " heos://browse/get_source_info?sid=" + QVariant(sourceId).toByteArray() + "\r\n"; QByteArray cmd = " heos://browse/get_source_info?sid=" + QVariant(sourceId).toByteArray() + "\r\n";
qCDebug(dcDenon) << "Group volume up:" << cmd; qCDebug(dcDenon) << "Get source info:" << cmd;
m_socket->write(cmd); m_socket->write(cmd);
} }
void Heos::getSearchCriteria(SOURCE_ID sourceId) void Heos::getSearchCriteria(SOURCE_ID sourceId)
{ {
QByteArray cmd = "heos://browse/get_search_criteria?sid=" + QVariant(sourceId).toByteArray() + "\r\n"; QByteArray cmd = "heos://browse/get_search_criteria?sid=" + QVariant(sourceId).toByteArray() + "\r\n";
qCDebug(dcDenon) << "Group volume up:" << cmd; qCDebug(dcDenon) << "Get search criteria:" << cmd;
m_socket->write(cmd); m_socket->write(cmd);
} }
void Heos::browseSource(SOURCE_ID sourceId) void Heos::browseSource(const QString &sourceId)
{ {
QByteArray cmd = "heos://browse/browse?sid=" + QVariant(sourceId).toByteArray() + "\r\n"; QByteArray cmd = "heos://browse/browse?sid=" + sourceId.toUtf8() + "\r\n";
qCDebug(dcDenon) << "Group volume up:" << cmd; qCDebug(dcDenon) << "Browse source:" << cmd;
m_socket->write(cmd);
}
void Heos::browseSourceContainers(const QString &sourceId, const QString &containerId)
{
QByteArray cmd = "heos://browse/browse?";
QUrlQuery queryParams;
queryParams.addQueryItem("sid", sourceId);
queryParams.addQueryItem("cid", containerId);
cmd.append(queryParams.toString());
cmd.append("\r\n");
qCDebug(dcDenon) << "playing station:" << cmd;
m_socket->write(cmd); m_socket->write(cmd);
} }
@ -648,6 +660,50 @@ void Heos::readData()
qDebug(dcDenon()) << "Playing Url"; qDebug(dcDenon()) << "Playing Url";
} }
} }
if (command.contains("get_music_sources") || command.contains("get_source_info")) {
QVariantList payloadVariantList = jsonDoc.toVariant().toMap().value("payload").toList();
QList<MusicSourceObject> musicSources;
foreach (const QVariant &payloadEntryVariant, payloadVariantList) {
MusicSourceObject source;
source.name = payloadEntryVariant.toMap().value("name").toString();
source.image_url = payloadEntryVariant.toMap().value("image_url").toString();
source.type = payloadEntryVariant.toMap().value("type").toString();
source.sourceId = payloadEntryVariant.toMap().value("sid").toInt();
source.available = payloadEntryVariant.toMap().value("available").toString().contains("true");
source.serviceUsername = payloadEntryVariant.toMap().value("service_username").toString();
musicSources.append(source);
}
emit musicSourcesReceived(musicSources);
}
if (command.contains("browse/browse")) {
QVariantList payloadVariantList = jsonDoc.toVariant().toMap().value("payload").toList();
QList<MusicSourceObject> musicSources;
QList<MediaObject> mediaItems;
foreach (const QVariant &payloadEntryVariant, payloadVariantList) {
QString type = payloadEntryVariant.toMap().value("type").toString();
if (type == "source") {
MusicSourceObject source;
source.name = payloadEntryVariant.toMap().value("name").toString();
source.image_url = payloadEntryVariant.toMap().value("image_url").toString();
source.type = payloadEntryVariant.toMap().value("type").toString();
source.sourceId = payloadEntryVariant.toMap().value("sid").toInt();
source.available = payloadEntryVariant.toMap().value("available").toString().contains("true");
source.serviceUsername = payloadEntryVariant.toMap().value("service_username").toString();
musicSources.append(source);
} else if (type == "container" || type == "album" || type == "song") {
MediaObject media;
media.name = payloadEntryVariant.toMap().value("name").toString();
media.imageUrl = payloadEntryVariant.toMap().value("image_url").toString();
mediaItems.append(media);
}
if (!mediaItems.isEmpty())
emit mediaItemsReceived(mediaItems);
if (!musicSources.isEmpty())
emit musicSourcesReceived(musicSources);
}
}
} }
} }
} }

View File

@ -34,6 +34,7 @@
#include <QObject> #include <QObject>
#include <QHostAddress> #include <QHostAddress>
#include <QTcpSocket> #include <QTcpSocket>
#include <QUuid>
#include "heosplayer.h" #include "heosplayer.h"
#include "heostypes.h" #include "heostypes.h"
@ -99,7 +100,9 @@ public:
void getMusicSources(); void getMusicSources();
void getSourceInfo(SOURCE_ID sourceId); void getSourceInfo(SOURCE_ID sourceId);
void getSearchCriteria(SOURCE_ID sourceId); void getSearchCriteria(SOURCE_ID sourceId);
void browseSource(SOURCE_ID sourceId); void browseSource(const QString &sourceId);
void browseSourceContainers(const QString &sourceId, const QString &containerId);
//void search(); //void search();
//Play commands //Play commands
@ -125,6 +128,8 @@ signals:
void muteStatusReceived(int playerId, bool mute); void muteStatusReceived(int playerId, bool mute);
void volumeStatusReceived(int playerId, int volume); void volumeStatusReceived(int playerId, int volume);
void nowPlayingMediaStatusReceived(int playerId, SOURCE_ID source, QString artist, QString album, QString Song, QString artwork); void nowPlayingMediaStatusReceived(int playerId, SOURCE_ID source, QString artist, QString album, QString Song, QString artwork);
void musicSourcesReceived(QList<MusicSourceObject> musicSources);
void mediaItemsReceived(QList<MediaObject> mediaItems);
private slots: private slots:
void onConnected(); void onConnected();

View File

@ -93,6 +93,15 @@ enum SEARCH_CRITERIA { // criteria id returned by 'get_search_criteria' com
SEARCH_CRITERIA_STATION SEARCH_CRITERIA_STATION
}; };
enum MEDIA_TYPE {
MEDIA_TYPE_SONG,
MEDIA_TYPE_STATION,
MEDIA_TYPE_GENRE,
MEDIA_TYPE_ARTIST,
MEDIA_TYPE_ALBUM,
MEDIA_TYPE_CONTAINER
};
enum SOURCE_ID { enum SOURCE_ID {
SOURCE_ID_PANDORA = 1, SOURCE_ID_PANDORA = 1,
SOURCE_ID_RHAPSODY, SOURCE_ID_RHAPSODY,
@ -156,6 +165,16 @@ struct SourceContainersObject {
int count; int count;
}; };
struct MediaObject {
MEDIA_TYPE mediaType;
bool isContainer;
bool isPlayable;
QString name;
QString imageUrl;
QString containerId;
QString mediaId;
};
struct heosPlayer { struct heosPlayer {
}; };

View File

@ -41,11 +41,11 @@
\chapter Plugin properties \chapter Plugin properties
Following JSON file contains the definition and the description of all available \l{ThingClass}{DeviceClasses} Following JSON file contains the definition and the description of all available \l{ThingClass}{DeviceClasses}
and \l{Vendor}{Vendors} of this \l{DevicePlugin}. and \l{Vendor}{Vendors} of this \l{IntegrationPlugin}.
For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}. For more details how to read this JSON file please check out the documentation for \l{The plugin JSON File}.
\quotefile plugins/deviceplugins/denon/deviceplugindenon.json \quotefile plugins/IntegrationPlugins/denon/IntegrationPlugindenon.json
*/ */
#include "integrationplugindenon.h" #include "integrationplugindenon.h"
@ -71,7 +71,7 @@ IntegrationPluginDenon::IntegrationPluginDenon()
void IntegrationPluginDenon::init() void IntegrationPluginDenon::init()
{ {
m_notificationUrl = QUrl(configValue(denonPluginNotificationUrlParamTypeId).toString()); m_notificationUrl = QUrl(configValue(denonPluginNotificationUrlParamTypeId).toString());
connect(this, &DevicePluginDenon::configValueChanged, this, &DevicePluginDenon::onPluginConfigurationChanged); connect(this, &IntegrationPluginDenon::configValueChanged, this, &IntegrationPluginDenon::onPluginConfigurationChanged);
} }
@ -117,10 +117,8 @@ void IntegrationPluginDenon::discoverThings(ThingDiscoveryInfo *info)
info->addThingDescriptor(thingDescriptor); info->addThingDescriptor(thingDescriptor);
} }
} }
info->finish(Thing::ThingErrorNoError); info->finish(Thing::ThingErrorNoError);
}); });
return; return;
} }
@ -188,6 +186,7 @@ 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::channelChanged, this, &IntegrationPluginDenon::onAvrChannelChanged); connect(denonConnection, &AvrConnection::channelChanged, this, &IntegrationPluginDenon::onAvrChannelChanged);
@ -196,7 +195,8 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info)
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);
m_avrConnections.insert(thing, 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, info, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); }); connect(info, &QObject::destroyed, this, [this, info, denonConnection]() { m_asyncAvrSetups.remove(denonConnection); });
@ -210,6 +210,7 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info)
QHostAddress address(thing->paramValue(heosThingIpParamTypeId).toString()); QHostAddress address(thing->paramValue(heosThingIpParamTypeId).toString());
Heos *heos = new Heos(address, this); Heos *heos = new Heos(address, this);
connect(heos, &Heos::connectionStatusChanged, this, &IntegrationPluginDenon::onHeosConnectionChanged); connect(heos, &Heos::connectionStatusChanged, this, &IntegrationPluginDenon::onHeosConnectionChanged);
connect(heos, &Heos::playerDiscovered, this, &IntegrationPluginDenon::onHeosPlayerDiscovered); connect(heos, &Heos::playerDiscovered, this, &IntegrationPluginDenon::onHeosPlayerDiscovered);
connect(heos, &Heos::playStateReceived, this, &IntegrationPluginDenon::onHeosPlayStateReceived); connect(heos, &Heos::playStateReceived, this, &IntegrationPluginDenon::onHeosPlayStateReceived);
@ -218,8 +219,10 @@ void IntegrationPluginDenon::setupThing(ThingSetupInfo *info)
connect(heos, &Heos::muteStatusReceived, this, &IntegrationPluginDenon::onHeosMuteStatusReceived); connect(heos, &Heos::muteStatusReceived, this, &IntegrationPluginDenon::onHeosMuteStatusReceived);
connect(heos, &Heos::volumeStatusReceived, this, &IntegrationPluginDenon::onHeosVolumeStatusReceived); connect(heos, &Heos::volumeStatusReceived, this, &IntegrationPluginDenon::onHeosVolumeStatusReceived);
connect(heos, &Heos::nowPlayingMediaStatusReceived, this, &IntegrationPluginDenon::onHeosNowPlayingMediaStatusReceived); connect(heos, &Heos::nowPlayingMediaStatusReceived, this, &IntegrationPluginDenon::onHeosNowPlayingMediaStatusReceived);
connect(heos, &Heos::musicSourcesReceived, this, &IntegrationPluginDenon::onHeosMusicSourcesReceived);
connect(heos, &Heos::mediaItemsReceived, this, &IntegrationPluginDenon::onHeosMediaItemsReceived);
m_heos.insert(thing->id(), heos);
m_heos.insert(thing, heos);
m_asyncHeosSetups.insert(heos, info); m_asyncHeosSetups.insert(heos, 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, info, heos]() { m_asyncHeosSetups.remove(heos); }); connect(info, &QObject::destroyed, this, [this, info, heos]() { m_asyncHeosSetups.remove(heos); });
@ -240,16 +243,16 @@ void IntegrationPluginDenon::thingRemoved(Thing *thing)
qCDebug(dcDenon) << "Delete " << thing->name(); qCDebug(dcDenon) << "Delete " << thing->name();
if (thing->thingClassId() == AVRX1000ThingClassId) { if (thing->thingClassId() == AVRX1000ThingClassId) {
AvrConnection *denonConnection = m_avrConnections.value(thing); AvrConnection *denonConnection = m_avrConnections.value(thing->id());
m_avrConnections.remove(thing); m_avrConnections.remove(thing->id());
denonConnection->disconnectDevice(); denonConnection->disconnectDevice();
denonConnection->deleteLater(); denonConnection->deleteLater();
} }
if (thing->thingClassId() == heosThingClassId) { if (thing->thingClassId() == heosThingClassId) {
if (m_avrConnections.contains(thing)) { if (m_avrConnections.contains(thing->id())) {
AvrConnection *denonConnection = m_avrConnections.value(thing); AvrConnection *denonConnection = m_avrConnections.take(thing->id());
m_avrConnections.remove(thing);
denonConnection->disconnectDevice(); denonConnection->disconnectDevice();
denonConnection->deleteLater(); denonConnection->deleteLater();
} }
@ -267,7 +270,7 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info)
qCDebug(dcDenon) << "Execute action" << thing->id() << action.id() << action.params(); qCDebug(dcDenon) << "Execute action" << thing->id() << action.id() << action.params();
if (thing->thingClassId() == AVRX1000ThingClassId) { if (thing->thingClassId() == AVRX1000ThingClassId) {
AvrConnection *avrConnection = m_avrConnections.value(thing); AvrConnection *avrConnection = m_avrConnections.value(thing->id());
if (action.actionTypeId() == AVRX1000PowerActionTypeId) { if (action.actionTypeId() == AVRX1000PowerActionTypeId) {
@ -310,7 +313,7 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info)
if (thing->thingClassId() == heosPlayerThingClassId) { if (thing->thingClassId() == heosPlayerThingClassId) {
Thing *heosThing = myThings().findById(thing->parentId()); Thing *heosThing = myThings().findById(thing->parentId());
Heos *heos = m_heos.value(heosThing); Heos *heos = m_heos.value(heosThing->id());
int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt(); int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt();
if (action.actionTypeId() == heosPlayerAlertActionTypeId) { if (action.actionTypeId() == heosPlayerAlertActionTypeId) {
@ -386,15 +389,16 @@ void IntegrationPluginDenon::executeAction(ThingActionInfo *info)
void IntegrationPluginDenon::postSetupThing(Thing *thing) void IntegrationPluginDenon::postSetupThing(Thing *thing)
{ {
if (thing->thingClassId() == heosThingClassId) { if (thing->thingClassId() == heosThingClassId) {
Heos *heos = m_heos.value(thing); Heos *heos = m_heos.value(thing->id());
heos->getPlayers(); heos->getPlayers();
} }
if (thing->thingClassId() == heosPlayerThingClassId) { if (thing->thingClassId() == heosPlayerThingClassId) {
thing->setStateValue(heosPlayerConnectedStateTypeId, true); thing->setStateValue(heosPlayerConnectedStateTypeId, true);
Thing *heosThing = myThings().findById(thing->parentId()); Thing *heosThing = myThings().findById(thing->parentId());
Heos *heos = m_heos.value(heosThing); Heos *heos = m_heos.value(heosThing->id());
int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt(); int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt();
heos->getPlayerState(playerId); heos->getPlayerState(playerId);
heos->getPlayMode(playerId); heos->getPlayMode(playerId);
heos->getVolume(playerId); heos->getVolume(playerId);
@ -415,7 +419,8 @@ void IntegrationPluginDenon::onPluginTimer()
if (!denonConnection->connected()) { if (!denonConnection->connected()) {
denonConnection->connectDevice(); denonConnection->connectDevice();
} }
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (thing->thingClassId() == AVRX1000ThingClassId) { if (thing->thingClassId() == AVRX1000ThingClassId) {
denonConnection->getAllStatus(); denonConnection->getAllStatus();
} }
@ -424,14 +429,14 @@ void IntegrationPluginDenon::onPluginTimer()
foreach(Thing *thing, myThings()) { foreach(Thing *thing, myThings()) {
if (thing->thingClassId() == heosThingClassId) { if (thing->thingClassId() == heosThingClassId) {
Heos *heos = m_heos.value(thing); Heos *heos = m_heos.value(thing->id());
heos->getPlayers(); heos->getPlayers();
heos->registerForChangeEvents(true); heos->registerForChangeEvents(true);
} }
if (thing->thingClassId() == heosPlayerThingClassId) { if (thing->thingClassId() == heosPlayerThingClassId) {
Thing *heosThing = myThings().findById(thing->parentId()); Thing *heosThing = myThings().findById(thing->parentId());
Heos *heos = m_heos.value(heosThing); Heos *heos = m_heos.value(heosThing->id());
int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt(); int playerId = thing->paramValue(heosPlayerThingPlayerIdParamTypeId).toInt();
heos->getPlayerState(playerId); heos->getPlayerState(playerId);
@ -446,7 +451,8 @@ 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 = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -466,7 +472,8 @@ void IntegrationPluginDenon::onAvrConnectionChanged(bool status)
void IntegrationPluginDenon::onAvrVolumeChanged(int volume) void IntegrationPluginDenon::onAvrVolumeChanged(int volume)
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -478,7 +485,7 @@ void IntegrationPluginDenon::onAvrVolumeChanged(int volume)
void IntegrationPluginDenon::onAvrChannelChanged(const QByteArray &channel) void IntegrationPluginDenon::onAvrChannelChanged(const QByteArray &channel)
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection); Thing *thing =myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -490,7 +497,8 @@ void IntegrationPluginDenon::onAvrChannelChanged(const QByteArray &channel)
void IntegrationPluginDenon::onAvrMuteChanged(bool mute) void IntegrationPluginDenon::onAvrMuteChanged(bool mute)
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -502,7 +510,8 @@ void IntegrationPluginDenon::onAvrMuteChanged(bool mute)
void IntegrationPluginDenon::onAvrPowerChanged(bool power) void IntegrationPluginDenon::onAvrPowerChanged(bool power)
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -514,7 +523,8 @@ void IntegrationPluginDenon::onAvrPowerChanged(bool power)
void IntegrationPluginDenon::onAvrSurroundModeChanged(const QByteArray &surroundMode) void IntegrationPluginDenon::onAvrSurroundModeChanged(const QByteArray &surroundMode)
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -527,7 +537,8 @@ void IntegrationPluginDenon::onAvrSurroundModeChanged(const QByteArray &surround
void IntegrationPluginDenon::onAvrSocketError() void IntegrationPluginDenon::onAvrSocketError()
{ {
AvrConnection *denonConnection = static_cast<AvrConnection *>(sender()); AvrConnection *denonConnection = static_cast<AvrConnection *>(sender());
Thing *thing = m_avrConnections.key(denonConnection);
Thing *thing = myThings().findById(m_avrConnections.key(denonConnection));
if (!thing) if (!thing)
return; return;
@ -541,7 +552,7 @@ void IntegrationPluginDenon::onAvrSocketError()
// Delete the connection, the thing will not be added and // Delete the connection, the thing will not be added and
// the connection will be created in the next setup // the connection will be created in the next setup
denonConnection->deleteLater(); denonConnection->deleteLater();
m_avrConnections.remove(thing); m_avrConnections.remove(thing->id());
} }
} }
} }
@ -550,7 +561,8 @@ void IntegrationPluginDenon::onHeosConnectionChanged(bool status)
{ {
Heos *heos = static_cast<Heos *>(sender()); Heos *heos = static_cast<Heos *>(sender());
heos->registerForChangeEvents(true); heos->registerForChangeEvents(true);
Thing *thing = m_heos.key(heos);
Thing *thing = myThings().findById(m_heos.key(heos));
if (!thing) if (!thing)
return; return;
@ -579,7 +591,8 @@ void IntegrationPluginDenon::onHeosConnectionChanged(bool status)
void IntegrationPluginDenon::onHeosPlayerDiscovered(HeosPlayer *heosPlayer) { void IntegrationPluginDenon::onHeosPlayerDiscovered(HeosPlayer *heosPlayer) {
Heos *heos = static_cast<Heos *>(sender()); Heos *heos = static_cast<Heos *>(sender());
Thing *thing = m_heos.key(heos);
Thing *thing = myThings().findById(m_heos.key(heos));
foreach (Thing *heosPlayerThing, myThings()) { foreach (Thing *heosPlayerThing, myThings()) {
if(heosPlayerThing->thingClassId() == heosPlayerThingClassId) { if(heosPlayerThing->thingClassId() == heosPlayerThingClassId) {
@ -737,6 +750,47 @@ void IntegrationPluginDenon::onHeosNowPlayingMediaStatusReceived(int playerId, S
} }
} }
void IntegrationPluginDenon::onHeosMusicSourcesReceived(QList<MusicSourceObject> musicSources)
{
Heos *heos = static_cast<Heos *>(sender());
if (m_pendingBrowseResult.contains(heos)) {
BrowseResult *result = m_pendingBrowseResult.take(heos);
foreach(MusicSourceObject source, musicSources) {
BrowserItem item;
item.setDisplayName(source.name);
//item.setDescription("test");
item.setId(QString::number(source.sourceId));
item.setThumbnail(source.image_url);
item.setExecutable(false);
item.setBrowsable(true);
result->addItem(item);
qDebug(dcDenon()) << "Music source received:" << source.name << source.type << source.sourceId << source.image_url;
}
result->finish(Device::DeviceErrorNoError);
}
}
void IntegrationPluginDenon::onHeosMediaItemsReceived(QList<MediaObject> mediaItems)
{
Heos *heos = static_cast<Heos *>(sender());
if (m_pendingBrowseResult.contains(heos)) {
BrowseResult *result = m_pendingBrowseResult.take(heos);
foreach(MediaObject media, mediaItems) {
BrowserItem item;
item.setDisplayName(media.name);
//item.setDescription("test");
item.setId(media.mediaId);
item.setThumbnail(media.imageUrl);
item.setExecutable(media.isPlayable);
item.setBrowsable(media.isContainer);
result->addItem(item);
qDebug(dcDenon()) << "Media received:" << media.name << media.mediaType << media.mediaId << media.imageUrl;
}
result->finish(Device::DeviceErrorNoError);
}
}
void IntegrationPluginDenon::onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry) void IntegrationPluginDenon::onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry)
{ {
qCDebug(dcDenon()) << "Avahi service entry added:" << serviceEntry; qCDebug(dcDenon()) << "Avahi service entry added:" << serviceEntry;
@ -747,7 +801,7 @@ void IntegrationPluginDenon::onAvahiServiceEntryRemoved(const ZeroConfServiceEnt
qCDebug(dcDenon()) << "Avahi service entry removed:" << serviceEntry; qCDebug(dcDenon()) << "Avahi service entry removed:" << serviceEntry;
} }
void DevicePluginDenon::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value) void IntegrationPluginDenon::onPluginConfigurationChanged(const ParamTypeId &paramTypeId, const QVariant &value)
{ {
qCDebug(dcDenon()) << "Plugin configuration changed"; qCDebug(dcDenon()) << "Plugin configuration changed";
@ -758,37 +812,44 @@ void DevicePluginDenon::onPluginConfigurationChanged(const ParamTypeId &paramTyp
} }
} }
void IntegrationPluginDenon::browseDevice(BrowseResult *result)
void DevicePluginDenon::browseDevice(BrowseResult *result)
{ {
Heos *heos = m_heos.value(result->device()); Heos *heos = m_heos.value(result->device()->parentId());
if (!heos) { if (!heos) {
result->finish(Device::DeviceErrorHardwareNotAvailable); result->finish(Device::DeviceErrorHardwareNotAvailable);
return; return;
} }
qDebug(dcDenon()) << "Browse device" << result->itemId() << result->locale();
m_pendingBrowseResult.insert(heos, result);
if (result->itemId().isEmpty()) {
heos->getMusicSources();
} else {
heos->browseSource(result->itemId());
}
//heos->browse(result); //heos->browse(result);
} }
void DevicePluginDenon::browserItem(BrowserItemResult *result) void IntegrationPluginDenon::browserItem(BrowserItemResult *result)
{ {
Heos *heos = m_heos.value(result->device()); Heos *heos = m_heos.value(result->device()->parentId());
if (!heos) { if (!heos) {
result->finish(Device::DeviceErrorHardwareNotAvailable); result->finish(Device::DeviceErrorHardwareNotAvailable);
return; return;
} }
qDebug(dcDenon()) << "Browse item called";
return; return;
} }
void DevicePluginDenon::executeBrowserItem(BrowserActionInfo *info) void IntegrationPluginDenon::executeBrowserItem(BrowserActionInfo *info)
{ {
Heos *heos = m_heos.value(info->device()); Heos *heos = m_heos.value(info->device()->parentId());
if (!heos) { if (!heos) {
info->finish(Device::DeviceErrorHardwareNotAvailable); info->finish(Device::DeviceErrorHardwareNotAvailable);
return; return;
} }
qDebug(dcDenon()) << "BExecute browse item called";
return;
/* /*
int id = kodi->launchBrowserItem(info->browserAction().itemId()); int id = kodi->launchBrowserItem(info->browserAction().itemId());
if (id == -1) { if (id == -1) {
@ -798,9 +859,9 @@ void DevicePluginDenon::executeBrowserItem(BrowserActionInfo *info)
connect(info, &QObject::destroyed, this, [this, id](){ m_pendingBrowserActions.remove(id); });*/ connect(info, &QObject::destroyed, this, [this, id](){ m_pendingBrowserActions.remove(id); });*/
} }
void DevicePluginDenon::executeBrowserItemAction(BrowserItemActionInfo *info) void IntegrationPluginDenon::executeBrowserItemAction(BrowserItemActionInfo *info)
{ {
Heos *kodi = m_heos.value(info->device()); Heos *kodi = m_heos.value(info->device()->parentId());
if (!kodi) { if (!kodi) {
info->finish(Device::DeviceErrorHardwareNotAvailable); info->finish(Device::DeviceErrorHardwareNotAvailable);
return; return;

View File

@ -63,7 +63,7 @@ public:
void executeAction(ThingActionInfo *info) override; void executeAction(ThingActionInfo *info) override;
void thingRemoved(Thing *thing) override; void thingRemoved(Thing *thing) override;
void browseDevice(BrowseResult *result) override; void browseThing(BrowseResult *result) override;
void browserItem(BrowserItemResult *result) override; void browserItem(BrowserItemResult *result) override;
void executeBrowserItem(BrowserActionInfo *info) override; void executeBrowserItem(BrowserActionInfo *info) override;
void executeBrowserItemAction(BrowserItemActionInfo *info) override; void executeBrowserItemAction(BrowserItemActionInfo *info) override;
@ -72,8 +72,8 @@ private:
PluginTimer *m_pluginTimer = nullptr; PluginTimer *m_pluginTimer = nullptr;
ZeroConfServiceBrowser *m_serviceBrowser = nullptr; ZeroConfServiceBrowser *m_serviceBrowser = nullptr;
QHash<Thing *, AvrConnection*> m_avrConnections; QHash<ThingId, AvrConnection*> m_avrConnections;
QHash<Thing *, Heos*> m_heos; QHash<ThingId, Heos*> m_heos;
QHash<AvrConnection*, ThingSetupInfo*> m_asyncAvrSetups; QHash<AvrConnection*, ThingSetupInfo*> m_asyncAvrSetups;
QHash<Heos*, ThingSetupInfo*> m_asyncHeosSetups; QHash<Heos*, ThingSetupInfo*> m_asyncHeosSetups;
@ -83,7 +83,8 @@ private:
QHash<const Action *, int> m_asyncActions; QHash<const Action *, int> m_asyncActions;
QUrl m_notificationUrl; QUrl m_notificationUrl;
QHash<int, DeviceActionInfo*> m_pendingActions; QHash<Heos *, BrowseResult*> m_pendingBrowseResult;
QHash<int, ThingActionInfo*> m_pendingActions;
QHash<int, BrowserActionInfo*> m_pendingBrowserActions; QHash<int, BrowserActionInfo*> m_pendingBrowserActions;
QHash<int, BrowserItemActionInfo*> m_pendingBrowserItemActions; QHash<int, BrowserItemActionInfo*> m_pendingBrowserItemActions;
@ -98,6 +99,9 @@ private slots:
void onHeosMuteStatusReceived(int playerId, bool mute); void onHeosMuteStatusReceived(int playerId, bool mute);
void onHeosVolumeStatusReceived(int playerId, int volume); void onHeosVolumeStatusReceived(int playerId, int volume);
void onHeosNowPlayingMediaStatusReceived(int playerId, SOURCE_ID source, QString artist, QString album, QString Song, QString artwork); void onHeosNowPlayingMediaStatusReceived(int playerId, SOURCE_ID source, QString artist, QString album, QString Song, QString artwork);
void onHeosMusicSourcesReceived(QList<MusicSourceObject> musicSources);
void onHeosMediaItemsReceived(QList<MediaObject> mediaItems);
void onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry); void onAvahiServiceEntryAdded(const ZeroConfServiceEntry &serviceEntry);
void onAvahiServiceEntryRemoved(const ZeroConfServiceEntry &serviceEntry); void onAvahiServiceEntryRemoved(const ZeroConfServiceEntry &serviceEntry);