added first level browsing

master
bernhard.trinnes 2020-03-17 11:44:50 +01:00
parent c1bc56d84a
commit 5d9b6c55e1
4 changed files with 215 additions and 22 deletions

View File

@ -78,7 +78,7 @@ QUuid BluOS::getStatus()
}
emit connectionChanged(true);
QByteArray data = reply->readAll();
qCDebug(dcBluOS()) << "Get Status:" << data;
//qCDebug(dcBluOS()) << "Get Status:" << data;
parseState(data);
});
return requestId;
@ -283,8 +283,9 @@ QUuid BluOS::listPresets()
}
emit connectionChanged(true);
QByteArray data = reply->readAll();
QXmlStreamReader xml;
xml.addData(reply->readAll());
xml.addData(data);
if (xml.hasError()) {
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
return;
@ -304,6 +305,7 @@ QUuid BluOS::listPresets()
if (xml.attributes().hasAttribute("url")) {
preset.Url = xml.attributes().value("url").toString();
}
qCDebug(dcBluOS()) << "Preset text" << xml.readElementText(); //apparently the text must be read so the xml parser recognises the next element
presetList.append(preset);
} else {
xml.skipCurrentElement();
@ -325,12 +327,13 @@ QUuid BluOS::loadPreset(int preset)
url.setScheme("http");
url.setHost(m_hostAddress.toString());
url.setPort(m_port);
url.setPath("/Presets");
url.setPath("/Preset");
QUrlQuery query;
query.addQueryItem("id", QString::number(preset));
url.setQuery(query);
qCDebug(dcBluOS()) << "Loading preset" << url.toString();
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, [reply, this] {
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@ -339,11 +342,12 @@ QUuid BluOS::loadPreset(int preset)
if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false);
}
emit actionExecuted(requestId, false);
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
return;
}
emit connectionChanged(true);
emit actionExecuted(requestId, true);
});
return requestId;
}
@ -358,7 +362,7 @@ QUuid BluOS::getSources()
url.setPort(m_port);
url.setPath("/Browse");
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, [reply, this] {
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@ -367,11 +371,110 @@ QUuid BluOS::getSources()
if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false);
}
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
return;
}
emit connectionChanged(true);
QByteArray data = reply->readAll();
qCDebug(dcBluOS()) << "Sources: " << data;
QXmlStreamReader xml;
xml.addData(data);
if (xml.hasError()) {
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
return;
}
QList<Source> sourceList;
if (xml.readNextStartElement()) {
if (xml.name() == "browse") {
while(xml.readNextStartElement()){
if(xml.name() == "item"){
Source source;
if (xml.attributes().hasAttribute("text")) {
source.Text = xml.attributes().value("text").toString();
}
if (xml.attributes().hasAttribute("type")) {
source.Type = xml.attributes().value("type").toString();
}
if (xml.attributes().hasAttribute("browseKey")) {
source.BrowseKey = xml.attributes().value("browseKey").toString();
}
if (xml.attributes().hasAttribute("image")) {
source.Image = xml.attributes().value("image").toString();
}
qCDebug(dcBluOS()) << "Source text" << xml.readElementText();
sourceList.append(source);
} else {
xml.skipCurrentElement();
}
}
}
}
emit sourcesReceived(requestId, sourceList);
});
return requestId;
}
QUuid BluOS::browseSource(const QString &key)
{
QUuid requestId = QUuid::createUuid();
QUrl url;
url.setScheme("http");
url.setHost(m_hostAddress.toString());
url.setPort(m_port);
url.setPath("/Browse");
QUrlQuery query;
query.addQueryItem("key", key);
url.setQuery(query);
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
reply->deleteLater();
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// Check HTTP status code
if (status != 200 || reply->error() != QNetworkReply::NoError) {
if (reply->error() == QNetworkReply::HostNotFoundError) {
emit connectionChanged(false);
}
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
return;
}
emit connectionChanged(true);
QByteArray data = reply->readAll();
qCDebug(dcBluOS()) << "Browse result: " << data;
QXmlStreamReader xml;
xml.addData(data);
if (xml.hasError()) {
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
return;
}
QList<Source> sourceList;
if (xml.readNextStartElement()) {
if (xml.name() == "browse") {
while(xml.readNextStartElement()){
if(xml.name() == "item"){
Source source;
if (xml.attributes().hasAttribute("text")) {
source.Text = xml.attributes().value("text").toString();
}
if (xml.attributes().hasAttribute("type")) {
source.Type = xml.attributes().value("type").toString();
}
if (xml.attributes().hasAttribute("browseKey")) {
source.BrowseKey = xml.attributes().value("browseKey").toString();
}
if (xml.attributes().hasAttribute("image")) {
source.Image = xml.attributes().value("image").toString();
}
qCDebug(dcBluOS()) << "Source text" << xml.readElementText();
sourceList.append(source);
} else {
xml.skipCurrentElement();
}
}
}
}
emit sourcesReceived(requestId, sourceList);
});
return requestId;
}

View File

@ -122,6 +122,7 @@ public:
// Content Browsing
QUuid getSources();
QUuid browseSource(const QString &key);
// Player Grouping
QUuid addGroupPlayer(QHostAddress address, int port); //adds player as slave
@ -144,5 +145,6 @@ signals:
void presetsReceived(QUuid requestId, const QList<Preset> &presets);
void sourcesReceived(QUuid requestId, const QList<Source> &sources);
void browseResultReceived(QUuid requestId, const QList<Source> &sources);
};
#endif // BLUOS_H

View File

@ -232,20 +232,28 @@ void IntegrationPluginBluOS::browseThing(BrowseResult *result)
QUuid requestId = bluos->listPresets();
m_asyncBrowseResults.insert(requestId, result);
connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);});
} else {
} else if (result->itemId() == "grouping") {
//TODO avahi discovery
// m_asyncBrowseResults.insert(requestId, result);
//connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);});
} else if (result->itemId().isEmpty()) {
MediaBrowserItem presetItem("presets", "Presets", true, false);
presetItem.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites);
presetItem.setMediaIcon(MediaBrowserItem::MediaBrowserIconMusicLibrary);
result->addItem(presetItem);
MediaBrowserItem groupingItem("grouping", "Grouping", true, false);
presetItem.setIcon(BrowserItem::BrowserIcon::BrowserIconApplication);
presetItem.setMediaIcon(MediaBrowserItem::MediaBrowserIconNetwork);
result->addItem(presetItem);
groupingItem.setIcon(BrowserItem::BrowserIcon::BrowserIconApplication);
groupingItem.setMediaIcon(MediaBrowserItem::MediaBrowserIconNetwork);
result->addItem(groupingItem);
QUuid requestId = bluos->getSources();
m_asyncBrowseResults.insert(requestId, result);
connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);});
} else {
QUuid requestId = bluos->browseSource(result->itemId());
m_asyncBrowseResults.insert(requestId, result);
connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);});
}
}
}
@ -274,7 +282,24 @@ void IntegrationPluginBluOS::browserItem(BrowserItemResult *result)
void IntegrationPluginBluOS::executeBrowserItem(BrowserActionInfo *info)
{
Q_UNUSED(info)
Thing *thing = info->thing();
if (thing->thingClassId() == bluosPlayerThingClassId) {
BluOS *bluos = m_bluos.value(thing->id());
if (!bluos)
return;
if (info->browserAction().itemId().startsWith("presets")) {
QUuid requestId;
int presetId = info->browserAction().itemId().split("&").last().toInt();
requestId = bluos->loadPreset(presetId);
m_asyncExecuteBrowseItems.insert(requestId, info);
connect(info, &BrowserActionInfo::aborted, this, [this, requestId]{m_asyncExecuteBrowseItems.remove(requestId);});
} else if (info->browserAction().itemId().startsWith("grouping")) {
//TODO Grouping
} else {
//TODO Sources
}
}
}
void IntegrationPluginBluOS::onConnectionChanged(bool connected)
@ -351,6 +376,15 @@ void IntegrationPluginBluOS::onActionExecuted(QUuid requestId, bool success)
info->finish(Thing::ThingErrorHardwareNotAvailable);
}
}
if (m_asyncExecuteBrowseItems.contains(requestId)) {
BrowserActionInfo *info = m_asyncExecuteBrowseItems.take(requestId);
if (success) {
info->finish(Thing::ThingErrorNoError);
} else {
info->finish(Thing::ThingErrorHardwareFailure);
}
m_pluginTimer->timeout(); // get a status update
}
}
void IntegrationPluginBluOS::onVolumeReceived(int volume, bool mute)
@ -369,10 +403,10 @@ void IntegrationPluginBluOS::onPresetsReceived(QUuid requestId, const QList<BluO
Thing *thing = myThings().findById(m_bluos.key(bluos));
if (!thing)
return;
Q_UNUSED(presets)
if (m_asyncBrowseResults.contains(requestId)) {
BrowseResult *result = m_asyncBrowseResults.take(requestId);
foreach(BluOS::Preset preset, presets) {
qCDebug(dcBluOS()) << "Preset added" << preset.Name << preset.Id << preset.Url;
BrowserItem item("presets&"+QString::number(preset.Id), preset.Name, false, true);
item.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites);
result->addItem(item);
@ -394,9 +428,63 @@ void IntegrationPluginBluOS::onSourcesReceived(QUuid requestId, const QList<BluO
if (m_asyncBrowseResults.contains(requestId)) {
BrowseResult *result = m_asyncBrowseResults.take(requestId);
foreach(BluOS::Source source, sources) {
BrowserItem item(source.BrowseKey, source.Text, false, true);
item.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites);
//TODO set media icons
qCDebug(dcBluOS()) << "Source added" << source.Text << source.BrowseKey << source.Type;
MediaBrowserItem item;
item.setDisplayName(source.Text);
if (source.BrowseKey.isEmpty()) {
item.setBrowsable(false);
item.setExecutable(true);
item.setId(source.Text);
} else {
item.setBrowsable(true);
item.setExecutable(false);
item.setId(source.BrowseKey);
}
item.setIcon(BrowserItem::BrowserIconMusic);
if (source.Text == "Bluetooth") {
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconBluetooth);
} else if (source.Text == "Spotify") {
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconSpotify);
item.setDescription("Open the Spotify App for browsing");
} else if (source.Text == "TuneIn") {
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconTuneIn);
} else if (source.Text.contains("Aux")) {
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconAux);
} else if (source.Text == "Radio Paradise") {
//item.setMediaIcon(MediaBrowserItem::MediaBrowserIconRadioParadise);
}
result->addItem(item);
}
result->finish(Thing::ThingErrorNoError);
}
if (m_asyncBrowseItemResults.contains(requestId)) {
BrowserItemResult *result = m_asyncBrowseItemResults.take(requestId);
Q_UNUSED(result)
}
}
void IntegrationPluginBluOS::onBrowseResultReceived(QUuid requestId, const QList<BluOS::Source> &sources)
{
BluOS *bluos = static_cast<BluOS*>(sender());
Thing *thing = myThings().findById(m_bluos.key(bluos));
if (!thing)
return;
if (m_asyncBrowseResults.contains(requestId)) {
BrowseResult *result = m_asyncBrowseResults.take(requestId);
foreach(BluOS::Source source, sources) {
qCDebug(dcBluOS()) << "Source added" << source.Text << source.BrowseKey << source.Type;
MediaBrowserItem item;
item.setDisplayName(source.Text);
if (source.BrowseKey.isEmpty()) {
item.setBrowsable(false);
item.setExecutable(true);
item.setId(source.Text);
} else {
item.setBrowsable(true);
item.setExecutable(false);
item.setId(source.BrowseKey);
}
item.setIcon(BrowserItem::BrowserIconMusic);
result->addItem(item);
}
result->finish(Thing::ThingErrorNoError);

View File

@ -86,6 +86,6 @@ private slots:
void onPresetsReceived(QUuid requestId, const QList<BluOS::Preset> &presets);
void onSourcesReceived(QUuid requestId, const QList<BluOS::Source> &sources);
void onBrowseResultReceived(QUuid requestId, const QList<BluOS::Source> &sources);
};
#endif // INTEGRATIONPLUGINBLUOS_H