added first level browsing
parent
c1bc56d84a
commit
5d9b6c55e1
117
bluos/bluos.cpp
117
bluos/bluos.cpp
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue