Merge PR #240: New integration plug-in: BluOS
This commit is contained in:
commit
e556fec5fd
24
bluos/README.md
Normal file
24
bluos/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# BluOS
|
||||
|
||||
This integration allows to control audio devices based on BluOS. BluOS is an operating system that can be found in products from Blusound, NAD Electronics, DALI Loudspeakers and others.
|
||||
|
||||
## Supported Things
|
||||
|
||||
* BluOS Player
|
||||
* Multimedia control
|
||||
* Volume
|
||||
* Browsing Presets
|
||||
* Browsing various music services
|
||||
* Grouping speakers
|
||||
* No internet or cloud connection required
|
||||
|
||||
## Requirements
|
||||
|
||||
* The BluOS device must be in the same local area network as nymea.
|
||||
* TCP sockets on port 80 must not be blocked by the router.
|
||||
* Blusound App to setup the speaker.
|
||||
* The package "nymea-plugin-bluos" must be installed
|
||||
|
||||
## More
|
||||
|
||||
https://www.bluesound.com/
|
||||
701
bluos/bluos.cpp
Normal file
701
bluos/bluos.cpp
Normal file
@ -0,0 +1,701 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "bluos.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QUrlQuery>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
BluOS::BluOS(NetworkAccessManager *networkmanager, QHostAddress hostAddress, int port, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_hostAddress(hostAddress),
|
||||
m_port(port),
|
||||
m_networkManager(networkmanager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int BluOS::port()
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
QHostAddress BluOS::hostAddress()
|
||||
{
|
||||
return m_hostAddress;
|
||||
}
|
||||
|
||||
void BluOS::getStatus()
|
||||
{
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Status");
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||
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()) << "Get Status:" << data;
|
||||
parseState(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid BluOS::setVolume(uint volume)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("level", QString::number(volume));
|
||||
query.addQueryItem("tell_slaves", "off");
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Volume");
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(reply->readAll());
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
|
||||
}
|
||||
int volume = 0;
|
||||
bool mute = false;
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == "volume") {
|
||||
if(xml.attributes().hasAttribute("mute")) {
|
||||
mute = xml.attributes().value("mute").toInt();
|
||||
}
|
||||
volume = xml.readElementText().toInt();
|
||||
}
|
||||
}
|
||||
emit volumeReceived(volume, mute);
|
||||
emit actionExecuted(requestId, true);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::setMute(bool mute)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("mute", QString::number(mute));
|
||||
query.addQueryItem("tell_slaves", "off");
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Volume");
|
||||
url.setQuery(query);
|
||||
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit actionExecuted(requestId, true);
|
||||
});
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::play()
|
||||
{
|
||||
return playBackControl(PlaybackCommand::Play);
|
||||
}
|
||||
|
||||
QUuid BluOS::pause()
|
||||
{
|
||||
return playBackControl(PlaybackCommand::Pause);
|
||||
}
|
||||
|
||||
QUuid BluOS::stop()
|
||||
{
|
||||
return playBackControl(PlaybackCommand::Stop);
|
||||
}
|
||||
|
||||
QUuid BluOS::back()
|
||||
{
|
||||
return playBackControl(PlaybackCommand::Back);
|
||||
}
|
||||
|
||||
QUuid BluOS::setShuffle(bool shuffle)
|
||||
{
|
||||
Q_UNUSED(shuffle)
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Shuffle");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("state", QString::number(shuffle));
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit actionExecuted(requestId, true);
|
||||
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(reply->readAll());
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
|
||||
return;
|
||||
}
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.attributes().hasAttribute("shuffle")) {
|
||||
bool shuffle = RepeatMode(xml.attributes().value("shuffle").toInt());
|
||||
emit shuffleStateReceived(shuffle);
|
||||
}
|
||||
}
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::setRepeat(RepeatMode repeatMode)
|
||||
{
|
||||
Q_UNUSED(repeatMode)
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Repeat");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("state", QString::number(repeatMode));
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit actionExecuted(requestId, true);
|
||||
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(reply->readAll());
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
|
||||
return;
|
||||
}
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == "playlist") {
|
||||
if (xml.attributes().hasAttribute("repeat")) {
|
||||
RepeatMode mode = RepeatMode(xml.attributes().value("repeat").toInt());
|
||||
emit repeatModeReceived(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::listPresets()
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Presets");
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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();
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(data);
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
|
||||
return;
|
||||
}
|
||||
QList<Preset> presetList;
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == "presets") {
|
||||
while(xml.readNextStartElement()){
|
||||
if(xml.name() == "preset"){
|
||||
Preset preset;
|
||||
if (xml.attributes().hasAttribute("id")) {
|
||||
preset.Id = xml.attributes().value("id").toInt();
|
||||
}
|
||||
if (xml.attributes().hasAttribute("name")) {
|
||||
preset.Name = xml.attributes().value("name").toString();
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emit presetsReceived(requestId, presetList);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::loadPreset(int preset)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
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, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
emit actionExecuted(requestId, true);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::getSources()
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/Browse");
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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()) << "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, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QUuid BluOS::addGroupPlayer(QHostAddress address, int port)
|
||||
{
|
||||
Q_UNUSED(address)
|
||||
Q_UNUSED(port)
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/AddSlave");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("slave", address.toString());
|
||||
query.addQueryItem("port", QString::number(port));
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||
|
||||
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);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::removeGroupPlayer(QHostAddress address, int port)
|
||||
{
|
||||
Q_UNUSED(address)
|
||||
Q_UNUSED(port)
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
url.setPath("/RemoveSlave");
|
||||
QUrlQuery query;
|
||||
query.addQueryItem("slave", address.toString());
|
||||
query.addQueryItem("port", QString::number(port));
|
||||
url.setQuery(query);
|
||||
QNetworkReply *reply = m_networkManager->get(QNetworkRequest(url));
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [reply, this] {
|
||||
|
||||
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);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
QUuid BluOS::skip()
|
||||
{
|
||||
return playBackControl(PlaybackCommand::Skip);
|
||||
}
|
||||
|
||||
QUuid BluOS::playBackControl(BluOS::PlaybackCommand command)
|
||||
{
|
||||
QUuid requestId = QUuid::createUuid();
|
||||
QUrl url;
|
||||
url.setScheme("http");
|
||||
url.setHost(m_hostAddress.toString());
|
||||
url.setPort(m_port);
|
||||
switch (command) {
|
||||
case PlaybackCommand::Play:
|
||||
url.setPath("/Play");
|
||||
break;
|
||||
case PlaybackCommand::Pause:
|
||||
url.setPath("/Pause");
|
||||
break;
|
||||
case PlaybackCommand::Stop:
|
||||
url.setPath("/Stop");
|
||||
break;
|
||||
case PlaybackCommand::Back:
|
||||
url.setPath("/Back");
|
||||
break;
|
||||
case PlaybackCommand::Skip:
|
||||
url.setPath("/Skip");
|
||||
break;
|
||||
}
|
||||
QNetworkRequest request;
|
||||
request.setUrl(url);
|
||||
QNetworkReply *reply = m_networkManager->get(request);
|
||||
qCDebug(dcBluOS()) << "Sending request" << request.url();
|
||||
connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater);
|
||||
connect(reply, &QNetworkReply::finished, this, [requestId, reply, this] {
|
||||
|
||||
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);
|
||||
}
|
||||
emit actionExecuted(requestId, false);
|
||||
qCWarning(dcBluOS()) << "Request error:" << status << reply->errorString();
|
||||
return;
|
||||
}
|
||||
emit connectionChanged(true);
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
parseState(data);
|
||||
});
|
||||
return requestId;
|
||||
}
|
||||
|
||||
bool BluOS::parseState(const QByteArray &state)
|
||||
{
|
||||
QXmlStreamReader xml;
|
||||
xml.addData(state);
|
||||
if (xml.hasError()) {
|
||||
qCDebug(dcBluOS()) << "XML Error:" << xml.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
StatusResponse statusResponse;
|
||||
if (xml.readNextStartElement()) {
|
||||
if (xml.name() == "status") {
|
||||
while(xml.readNextStartElement()){
|
||||
if(xml.name() == "artist"){
|
||||
statusResponse.Artist = xml.readElementText();
|
||||
} else if(xml.name() == "album"){
|
||||
statusResponse.Album = xml.readElementText();
|
||||
} else if(xml.name() == "name"){
|
||||
statusResponse.Name = xml.readElementText();
|
||||
} else if(xml.name() == "service"){
|
||||
statusResponse.Service = xml.readElementText();
|
||||
} else if(xml.name() == "serviceIcon"){
|
||||
statusResponse.ServiceIcon = xml.readElementText();
|
||||
} else if(xml.name() == "shuffle"){
|
||||
statusResponse.Shuffle = xml.readElementText().toInt();
|
||||
} else if(xml.name() == "repeat"){
|
||||
statusResponse.Shuffle = xml.readElementText().toInt();
|
||||
} else if(xml.name() == "state"){
|
||||
QString playback = xml.readElementText();
|
||||
if (playback == "play") {
|
||||
statusResponse.State = PlaybackState::Playing;
|
||||
} else if (playback == "pause") {
|
||||
statusResponse.State = PlaybackState::Paused;
|
||||
} else if (playback == "stop") {
|
||||
statusResponse.State = PlaybackState::Stopped;
|
||||
} else if (playback == "connecting") {
|
||||
statusResponse.State = PlaybackState::Connecting;
|
||||
} else if (playback == "stream") {
|
||||
statusResponse.State = PlaybackState::Streaming;
|
||||
} else {
|
||||
statusResponse.State = PlaybackState::Stopped;
|
||||
qCWarning(dcBluOS()) << "State response, unhandled playback mode" << playback;
|
||||
}
|
||||
} else if(xml.name() == "volume"){
|
||||
statusResponse.Volume = xml.readElementText().toInt();
|
||||
} else if(xml.name() == "mute"){
|
||||
statusResponse.Mute = xml.readElementText().toInt();
|
||||
} else if(xml.name() == "image") {
|
||||
statusResponse.Image = xml.readElementText();
|
||||
} else if(xml.name() == "title1") {
|
||||
statusResponse.Title = xml.readElementText();
|
||||
} else if(xml.name() == "group") {
|
||||
statusResponse.Group = xml.readElementText();
|
||||
} else {
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emit statusReceived(statusResponse);
|
||||
return true;
|
||||
}
|
||||
153
bluos/bluos.h
Normal file
153
bluos/bluos.h
Normal file
@ -0,0 +1,153 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef BLUOS_H
|
||||
#define BLUOS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QHostAddress>
|
||||
#include <QUuid>
|
||||
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "integrations/thing.h"
|
||||
|
||||
class BluOS : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum PlaybackCommand {
|
||||
Play,
|
||||
Pause,
|
||||
Stop,
|
||||
Skip,
|
||||
Back
|
||||
};
|
||||
|
||||
enum RepeatMode {
|
||||
All,
|
||||
One,
|
||||
None
|
||||
};
|
||||
|
||||
enum PlaybackState {
|
||||
Playing,
|
||||
Paused,
|
||||
Stopped,
|
||||
Connecting,
|
||||
Streaming
|
||||
};
|
||||
|
||||
struct StatusResponse {
|
||||
QString Album;
|
||||
QString Artist;
|
||||
QString Name;
|
||||
QString Title;
|
||||
QString Service;
|
||||
QUrl ServiceIcon;
|
||||
PlaybackState State;
|
||||
QUrl StationUrl;
|
||||
int Volume;
|
||||
bool Mute;
|
||||
RepeatMode Repeat;
|
||||
bool Shuffle;
|
||||
QUrl Image;
|
||||
QString Group;
|
||||
};
|
||||
|
||||
struct Preset {
|
||||
QString Name;
|
||||
int Id;
|
||||
QString Url;
|
||||
};
|
||||
|
||||
struct Source {
|
||||
//<item image="/images/ci_myplaylists.png" browseKey="playlists" text="Playlists" type="link"/>
|
||||
QString Image;
|
||||
QString BrowseKey;
|
||||
QString Text;
|
||||
QString Type;
|
||||
};
|
||||
|
||||
explicit BluOS(NetworkAccessManager *networkManager, QHostAddress hostAddress, int port, QObject *parent = nullptr);
|
||||
int port();
|
||||
QHostAddress hostAddress();
|
||||
|
||||
// Status Queries
|
||||
void getStatus();
|
||||
|
||||
// Volume Control
|
||||
QUuid setVolume(uint volume);
|
||||
QUuid setMute(bool mute);
|
||||
|
||||
// Playback Control
|
||||
QUuid play();
|
||||
QUuid pause();
|
||||
QUuid stop();
|
||||
QUuid skip();
|
||||
QUuid back();
|
||||
QUuid setShuffle(bool shuffle);
|
||||
QUuid setRepeat(RepeatMode repeatMode);
|
||||
|
||||
// Presets
|
||||
QUuid listPresets();
|
||||
QUuid loadPreset(int preset); //1 for next preset, -1 for previous preset
|
||||
|
||||
// Content Browsing
|
||||
QUuid getSources();
|
||||
QUuid browseSource(const QString &key);
|
||||
|
||||
// Player Grouping
|
||||
QUuid addGroupPlayer(QHostAddress address, int port); //adds player as slave
|
||||
QUuid removeGroupPlayer(QHostAddress address, int port);
|
||||
|
||||
private:
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
NetworkAccessManager *m_networkManager = nullptr;
|
||||
|
||||
QUuid playBackControl(PlaybackCommand command);
|
||||
bool parseState(const QByteArray &state);
|
||||
|
||||
signals:
|
||||
void connectionChanged(bool connected);
|
||||
void actionExecuted(QUuid actionId, bool success);
|
||||
|
||||
void statusReceived(const StatusResponse &status);
|
||||
void volumeReceived(int volume, bool mute);
|
||||
void shuffleStateReceived(bool state);
|
||||
void repeatModeReceived(RepeatMode mode);
|
||||
|
||||
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
|
||||
11
bluos/bluos.pro
Normal file
11
bluos/bluos.pro
Normal file
@ -0,0 +1,11 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginbluos.cpp \
|
||||
bluos.cpp \
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginbluos.h \
|
||||
bluos.h \
|
||||
BIN
bluos/blusound.png
Normal file
BIN
bluos/blusound.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
568
bluos/integrationpluginbluos.cpp
Normal file
568
bluos/integrationpluginbluos.cpp
Normal file
@ -0,0 +1,568 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
#include "integrationpluginbluos.h"
|
||||
#include "plugininfo.h"
|
||||
#include "integrations/thing.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "types/mediabrowseritem.h"
|
||||
#include "types/browseritem.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QJsonDocument>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
IntegrationPluginBluOS::IntegrationPluginBluOS()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::init()
|
||||
{
|
||||
m_serviceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_musc._tcp");
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
QTimer::singleShot(5000, info, [this, info](){
|
||||
foreach (const ZeroConfServiceEntry avahiEntry, m_serviceBrowser->serviceEntries()) {
|
||||
qCDebug(dcBluOS()) << "Zeroconf entry:" << avahiEntry;
|
||||
|
||||
QString playerId = avahiEntry.hostName().split(".").first();
|
||||
ThingDescriptor descriptor(bluosPlayerThingClassId, avahiEntry.name(), avahiEntry.hostAddress().toString());
|
||||
ParamList params;
|
||||
|
||||
foreach (Thing *existingDevice, myThings().filterByThingClassId(bluosPlayerThingClassId)) {
|
||||
if (existingDevice->paramValue(bluosPlayerThingSerialNumberParamTypeId).toString() == playerId) {
|
||||
descriptor.setThingId(existingDevice->id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
params << Param(bluosPlayerThingAddressParamTypeId, avahiEntry.hostAddress().toString());
|
||||
params << Param(bluosPlayerThingPortParamTypeId, avahiEntry.port());
|
||||
params << Param(bluosPlayerThingSerialNumberParamTypeId, playerId);
|
||||
descriptor.setParams(params);
|
||||
info->addThingDescriptor(descriptor);
|
||||
}
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
});
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
qCDebug(dcBluOS()) << "Setup BluOS device" << thing->paramValue(bluosPlayerThingAddressParamTypeId).toString();
|
||||
|
||||
QHostAddress address(thing->paramValue(bluosPlayerThingAddressParamTypeId).toString());
|
||||
int port = thing->paramValue(bluosPlayerThingPortParamTypeId).toInt();
|
||||
BluOS *bluos = new BluOS(hardwareManager()->networkManager() , address, port, this);
|
||||
connect(bluos, &BluOS::connectionChanged, this, &IntegrationPluginBluOS::onConnectionChanged);
|
||||
connect(bluos, &BluOS::statusReceived, this, &IntegrationPluginBluOS::onStatusResponseReceived);
|
||||
connect(bluos, &BluOS::actionExecuted, this, &IntegrationPluginBluOS::onActionExecuted);
|
||||
connect(bluos, &BluOS::volumeReceived, this, &IntegrationPluginBluOS::onVolumeReceived);
|
||||
connect(bluos, &BluOS::presetsReceived, this, &IntegrationPluginBluOS::onPresetsReceived);
|
||||
connect(bluos, &BluOS::sourcesReceived, this, &IntegrationPluginBluOS::onSourcesReceived);
|
||||
connect(bluos, &BluOS::shuffleStateReceived, this, &IntegrationPluginBluOS::onShuffleStateReceived);
|
||||
connect(bluos, &BluOS::repeatModeReceived, this, &IntegrationPluginBluOS::onRepeatModeReceived);
|
||||
|
||||
m_asyncSetup.insert(bluos, info);
|
||||
bluos->getStatus();
|
||||
// In case the setup is cancelled before we finish it...
|
||||
connect(info, &ThingSetupInfo::aborted, this, [this, bluos] {
|
||||
m_asyncSetup.remove(bluos);
|
||||
bluos->deleteLater();
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
return info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::postSetupThing(Thing *thing)
|
||||
{
|
||||
Q_UNUSED(thing)
|
||||
|
||||
if (!m_pluginTimer) {
|
||||
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
|
||||
connect(m_pluginTimer, &PluginTimer::timeout, [this] {
|
||||
foreach(BluOS *bluos, m_bluos) {
|
||||
bluos->getStatus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::thingRemoved(Thing *thing)
|
||||
{
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
BluOS *bluos = m_bluos.take(thing->id());
|
||||
bluos->deleteLater();
|
||||
} else {
|
||||
qCWarning(dcBluOS()) << "Things removed, unhandled thing class id";
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::executeAction(ThingActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
Action action = info->action();
|
||||
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
BluOS *bluos = m_bluos.value(thing->id());
|
||||
if (!bluos) {
|
||||
return info->finish(Thing::ThingErrorHardwareFailure);
|
||||
}
|
||||
if (action.actionTypeId() == bluosPlayerPlaybackStatusActionTypeId) {
|
||||
QString playbakStatus = action.param(bluosPlayerPlaybackStatusEventPlaybackStatusParamTypeId).value().toString();
|
||||
QUuid requestId;
|
||||
if (playbakStatus == "Playing") {
|
||||
requestId = bluos->play();
|
||||
} else if (playbakStatus == "Paused") {
|
||||
requestId = bluos->pause();
|
||||
} else if (playbakStatus == "Stopped") {
|
||||
requestId = bluos->stop();
|
||||
} else {
|
||||
qCWarning(dcBluOS()) << "Unhandled Playback mode";
|
||||
}
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerPlayActionTypeId) {
|
||||
QUuid requestId = bluos->play();
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerPauseActionTypeId) {
|
||||
QUuid requestId = bluos->pause();
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerStopActionTypeId) {
|
||||
QUuid requestId = bluos->stop();
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerSkipNextActionTypeId) {
|
||||
QUuid requestId = bluos->skip();
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerSkipBackActionTypeId) {
|
||||
QUuid requestId = bluos->back();
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerVolumeActionTypeId) {
|
||||
uint volume = action.param(bluosPlayerVolumeActionVolumeParamTypeId).value().toUInt();
|
||||
QUuid requestId = bluos->setVolume(volume);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerMuteActionTypeId) {
|
||||
bool mute = action.param(bluosPlayerMuteActionMuteParamTypeId).value().toBool();
|
||||
QUuid requestId = bluos->setMute(mute);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerShuffleActionTypeId) {
|
||||
bool shuffle = action.param(bluosPlayerShuffleActionShuffleParamTypeId).value().toBool();
|
||||
QUuid requestId = bluos->setShuffle(shuffle);
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else if (action.actionTypeId() == bluosPlayerRepeatActionTypeId) {
|
||||
QString repeat = action.param(bluosPlayerRepeatActionRepeatParamTypeId).value().toString();
|
||||
QUuid requestId;
|
||||
if (repeat == "One") {
|
||||
requestId = bluos->setRepeat(BluOS::RepeatMode::One);
|
||||
} else if (repeat == "All") {
|
||||
requestId = bluos->setRepeat(BluOS::RepeatMode::All);
|
||||
} else if (repeat == "None") {
|
||||
requestId = bluos->setRepeat(BluOS::RepeatMode::None);
|
||||
} else {
|
||||
qCWarning(dcBluOS()) << "Unhandled Repeat Mode";
|
||||
}
|
||||
m_asyncActions.insert(requestId, info);
|
||||
connect(info, &ThingActionInfo::aborted, [this, requestId] {m_asyncActions.remove(requestId);});
|
||||
} else {
|
||||
qCWarning(dcBluOS()) << "Execute Action, unhandled action type id" << action.actionTypeId();
|
||||
return info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
} else {
|
||||
qCWarning(dcBluOS()) << "Execute Action, unhandled thing class id" << thing->thingClassId();
|
||||
return info->finish(Thing::ThingErrorThingClassNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::browseThing(BrowseResult *result)
|
||||
{
|
||||
Thing *thing = result->thing();
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
BluOS *bluos = m_bluos.value(thing->id());
|
||||
if (!bluos) {
|
||||
qCWarning(dcBluOS()) << "Could not find any BluOS object that belongs to" << thing->name();
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable, "BluOS connection not properly initialized");
|
||||
return;
|
||||
}
|
||||
if (result->itemId() == "presets") {
|
||||
QUuid requestId = bluos->listPresets();
|
||||
m_asyncBrowseResults.insert(requestId, result);
|
||||
connect(result, &BrowseResult::aborted, this, [this, requestId]{m_asyncBrowseResults.remove(requestId);});
|
||||
} else if (result->itemId() == "grouping") {
|
||||
foreach (const ZeroConfServiceEntry avahiEntry, m_serviceBrowser->serviceEntries()) {
|
||||
qCDebug(dcBluOS()) << "Zeroconf entry:" << avahiEntry;
|
||||
|
||||
QString playerId = avahiEntry.hostName().split(".").first();
|
||||
if (thing->paramValue(bluosPlayerThingSerialNumberParamTypeId).toString() == playerId) {
|
||||
continue;
|
||||
}
|
||||
MediaBrowserItem groupingItem("grouping&"+avahiEntry.hostAddress().toString()+"&"+avahiEntry.port(), avahiEntry.name(), true, false);
|
||||
groupingItem.setDescription(avahiEntry.hostAddress().toString());
|
||||
groupingItem.setMediaIcon(MediaBrowserItem::MediaBrowserIconNetwork);
|
||||
groupingItem.setIcon(BrowserItem::BrowserIconMusic);
|
||||
result->addItem(groupingItem);
|
||||
}
|
||||
} 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);
|
||||
// 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);});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::browserItem(BrowserItemResult *result)
|
||||
{
|
||||
Thing *thing = result->thing();
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
BluOS *bluos = m_bluos.value(thing->id());
|
||||
if (!bluos) {
|
||||
qCWarning(dcBluOS()) << "Could not find any BluOS object that belongs to" << thing->name();
|
||||
return;
|
||||
}
|
||||
if (result->itemId() == "presets") {
|
||||
QUuid requestId = bluos->listPresets();
|
||||
m_asyncBrowseItemResults.insert(requestId, result);
|
||||
connect(result, &BrowserItemResult::aborted, this, [this, requestId]{m_asyncBrowseItemResults.remove(requestId);});
|
||||
} else {
|
||||
BrowserItem presetItem("presets", "Presets", true, false);
|
||||
presetItem.setIcon(BrowserItem::BrowserIcon::BrowserIconFavorites);
|
||||
QUuid requestId = bluos->getSources();
|
||||
m_asyncBrowseItemResults.insert(requestId, result);
|
||||
connect(result, &BrowserItemResult::aborted, this, [this, requestId]{m_asyncBrowseItemResults.remove(requestId);});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::executeBrowserItem(BrowserActionInfo *info)
|
||||
{
|
||||
Thing *thing = info->thing();
|
||||
if (thing->thingClassId() == bluosPlayerThingClassId) {
|
||||
BluOS *bluos = m_bluos.value(thing->id());
|
||||
if (!bluos) {
|
||||
qCWarning(dcBluOS()) << "Could not find any BluOS object that belongs to" << thing->name();
|
||||
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
|
||||
//Test devices are required
|
||||
} else {
|
||||
//TODO Sources
|
||||
//Test services are required
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onConnectionChanged(bool connected)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
|
||||
if (m_asyncSetup.contains(bluos)) {
|
||||
ThingSetupInfo *info = m_asyncSetup.take(bluos);
|
||||
if (connected) {
|
||||
m_bluos.insert(info->thing()->id(), bluos);
|
||||
info->thing()->setStateValue(bluosPlayerConnectedStateTypeId, true);
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
bluos->deleteLater();
|
||||
info->finish(Thing::ThingErrorSetupFailed);
|
||||
}
|
||||
} else {
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
if (!thing) {
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to the BluOS object";
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(bluosPlayerConnectedStateTypeId, connected);
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onStatusResponseReceived(const BluOS::StatusResponse &status)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
if (!thing){
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this BluOS object";
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(bluosPlayerArtistStateTypeId, status.Artist);
|
||||
thing->setStateValue(bluosPlayerCollectionStateTypeId, status.Album);
|
||||
thing->setStateValue(bluosPlayerTitleStateTypeId, status.Title);
|
||||
thing->setStateValue(bluosPlayerSourceStateTypeId, status.Service);
|
||||
thing->setStateValue(bluosPlayerArtworkStateTypeId, status.Image);
|
||||
switch (status.State) {
|
||||
case BluOS::PlaybackState::Playing:
|
||||
case BluOS::PlaybackState::Streaming:
|
||||
thing->setStateValue(bluosPlayerPlaybackStatusStateTypeId, "Playing");
|
||||
break;
|
||||
case BluOS::PlaybackState::Paused:
|
||||
thing->setStateValue(bluosPlayerPlaybackStatusStateTypeId, "Paused");
|
||||
break;
|
||||
case BluOS::PlaybackState::Stopped:
|
||||
thing->setStateValue(bluosPlayerPlaybackStatusStateTypeId, "Stopped");
|
||||
break;
|
||||
default:
|
||||
thing->setStateValue(bluosPlayerPlaybackStatusStateTypeId, "Stopped");
|
||||
break;
|
||||
}
|
||||
|
||||
thing->setStateValue(bluosPlayerMuteStateTypeId, status.Mute);
|
||||
thing->setStateValue(bluosPlayerVolumeStateTypeId, status.Volume);
|
||||
thing->setStateValue(bluosPlayerShuffleStateTypeId, status.Shuffle);
|
||||
switch (status.Repeat) {
|
||||
case BluOS::RepeatMode::All:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "All");
|
||||
break;
|
||||
case BluOS::RepeatMode::One:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "One");
|
||||
break;
|
||||
case BluOS::RepeatMode::None:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "None");
|
||||
break;
|
||||
}
|
||||
thing->setStateValue(bluosPlayerGroupStateTypeId, status.Group);
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onActionExecuted(QUuid requestId, bool success)
|
||||
{
|
||||
if (m_asyncActions.contains(requestId)) {
|
||||
ThingActionInfo *info = m_asyncActions.take(requestId);
|
||||
if (success) {
|
||||
info->finish(Thing::ThingErrorNoError);
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
if (!thing){
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this BluOS object";
|
||||
return;
|
||||
}
|
||||
thing->setStateValue(bluosPlayerMuteStateTypeId, mute);
|
||||
thing->setStateValue(bluosPlayerVolumeStateTypeId, volume);
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onShuffleStateReceived(bool state)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
if (!thing)
|
||||
return;
|
||||
thing->setStateValue(bluosPlayerShuffleStateTypeId, state);
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onRepeatModeReceived(BluOS::RepeatMode mode)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
if (!thing){
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this BluOS object";
|
||||
return;
|
||||
}
|
||||
switch (mode) {
|
||||
case BluOS::RepeatMode::All:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "All");
|
||||
break;
|
||||
case BluOS::RepeatMode::One:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "One");
|
||||
break;
|
||||
case BluOS::RepeatMode::None:
|
||||
thing->setStateValue(bluosPlayerRepeatStateTypeId, "None");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onPresetsReceived(QUuid requestId, const QList<BluOS::Preset> &presets)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
|
||||
if (m_asyncBrowseResults.contains(requestId)) {
|
||||
BrowseResult *result = m_asyncBrowseResults.take(requestId);
|
||||
if (!thing) {
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this browse result";
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
result->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
if (m_asyncBrowseItemResults.contains(requestId)) {
|
||||
BrowserItemResult *result = m_asyncBrowseItemResults.take(requestId);
|
||||
result->finish(Thing::ThingErrorItemNotFound);
|
||||
//For future browsing features
|
||||
}
|
||||
}
|
||||
|
||||
void IntegrationPluginBluOS::onSourcesReceived(QUuid requestId, const QList<BluOS::Source> &sources)
|
||||
{
|
||||
BluOS *bluos = static_cast<BluOS*>(sender());
|
||||
Thing *thing = myThings().findById(m_bluos.key(bluos));
|
||||
|
||||
if (m_asyncBrowseResults.contains(requestId)) {
|
||||
BrowseResult *result = m_asyncBrowseResults.take(requestId);
|
||||
if (!thing) {
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this browse result";
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
if (source.Text == "Bluetooth") {
|
||||
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconBluetooth);
|
||||
//result->addItem(item);
|
||||
} else if (source.Text == "Spotify") {
|
||||
item.setExecutable(false);
|
||||
item.setBrowsable(false);
|
||||
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconSpotify);
|
||||
item.setDescription("Open the Spotify App for browsing");
|
||||
result->addItem(item);
|
||||
} else if (source.Text == "TuneIn") {
|
||||
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconTuneIn);
|
||||
result->addItem(item);
|
||||
} else if (source.Text.contains("Aux")) {
|
||||
item.setMediaIcon(MediaBrowserItem::MediaBrowserIconAux);
|
||||
result->addItem(item);
|
||||
} else if (source.Text == "Radio Paradise") {
|
||||
//item.setMediaIcon(MediaBrowserItem::MediaBrowserIconRadioParadise);
|
||||
//result->addItem(item);
|
||||
//Needs testing before continuing
|
||||
}
|
||||
}
|
||||
result->finish(Thing::ThingErrorNoError);
|
||||
}
|
||||
|
||||
if (m_asyncBrowseItemResults.contains(requestId)) {
|
||||
BrowserItemResult *result = m_asyncBrowseItemResults.take(requestId);
|
||||
result->finish(Thing::ThingErrorItemNotFound);
|
||||
//For future browsing features
|
||||
}
|
||||
}
|
||||
|
||||
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 (m_asyncBrowseResults.contains(requestId)) {
|
||||
BrowseResult *result = m_asyncBrowseResults.take(requestId);
|
||||
|
||||
if (!thing) {
|
||||
qCWarning(dcBluOS()) << "Could not find any Thing that belongs to this browse result";
|
||||
result->finish(Thing::ThingErrorHardwareNotAvailable);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
92
bluos/integrationpluginbluos.h
Normal file
92
bluos/integrationpluginbluos.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
* This project including source code and documentation is protected by
|
||||
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||
* reproduction, publication, editing and translation, are reserved. The use of
|
||||
* this project is subject to the terms of a license agreement to be concluded
|
||||
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||
* under https://nymea.io/license
|
||||
*
|
||||
* GNU Lesser General Public License Usage
|
||||
* Alternatively, this project may be redistributed and/or modified under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; version 3. This project is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this project. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* For any further details and any questions please contact us under
|
||||
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||
* https://nymea.io/license/faq
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifndef INTEGRATIONPLUGINBLUOS_H
|
||||
#define INTEGRATIONPLUGINBLUOS_H
|
||||
|
||||
#include "bluos.h"
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
#include "network/zeroconf/zeroconfservicebrowser.h"
|
||||
#include "plugintimer.h"
|
||||
|
||||
#include <QUdpSocket>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
class PluginTimer;
|
||||
|
||||
class IntegrationPluginBluOS: public IntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginbluos.json")
|
||||
Q_INTERFACES(IntegrationPlugin)
|
||||
|
||||
public:
|
||||
explicit IntegrationPluginBluOS();
|
||||
|
||||
void init() override;
|
||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||
void setupThing(ThingSetupInfo *info) override;
|
||||
void postSetupThing(Thing *thing) override;
|
||||
void thingRemoved(Thing *thing) override;
|
||||
void executeAction(ThingActionInfo *info) override;
|
||||
|
||||
void browseThing(BrowseResult *result) override;
|
||||
void browserItem(BrowserItemResult *result) override;
|
||||
void executeBrowserItem(BrowserActionInfo *info) override;
|
||||
|
||||
private:
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
ZeroConfServiceBrowser *m_serviceBrowser = nullptr;
|
||||
|
||||
QHash<ThingId, BluOS *> m_bluos;
|
||||
QHash<BluOS *, ThingSetupInfo *> m_asyncSetup;
|
||||
QHash<QUuid, ThingActionInfo *> m_asyncActions;
|
||||
QHash<QUuid, BrowseResult *> m_asyncBrowseResults;
|
||||
QHash<QUuid, BrowserActionInfo *> m_asyncExecuteBrowseItems;
|
||||
QHash<QUuid, BrowserItemResult *> m_asyncBrowseItemResults;
|
||||
|
||||
private slots:
|
||||
void onPluginTimer();
|
||||
|
||||
void onConnectionChanged(bool connected);
|
||||
void onStatusResponseReceived(const BluOS::StatusResponse &status);
|
||||
void onActionExecuted(QUuid actionId, bool success);
|
||||
void onVolumeReceived(int volume, bool mute);
|
||||
void onShuffleStateReceived(bool state);
|
||||
void onRepeatModeReceived(BluOS::RepeatMode mode);
|
||||
|
||||
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
|
||||
198
bluos/integrationpluginbluos.json
Normal file
198
bluos/integrationpluginbluos.json
Normal file
@ -0,0 +1,198 @@
|
||||
{
|
||||
"displayName": "BluOS",
|
||||
"name": "BluOS",
|
||||
"id": "71dd25b3-37ef-4b27-abca-24989fa38c61",
|
||||
"vendors": [
|
||||
{
|
||||
"id": "39a492e9-e497-4b43-94d4-970eb9913b96",
|
||||
"displayName": "BluOS",
|
||||
"name": "bluos",
|
||||
"thingClasses": [
|
||||
{
|
||||
"id": "406adcbc-1e7d-4e41-ae2a-f87b6bafd13d",
|
||||
"name": "bluosPlayer",
|
||||
"displayName": "BluOS player",
|
||||
"createMethods": ["discovery"],
|
||||
"interfaces": ["mediaplayer", "extendedvolumecontroller", "mediametadataprovider", "shufflerepeat", "connectable"],
|
||||
"browsable": true,
|
||||
"paramTypes":[
|
||||
{
|
||||
"id": "833f99cc-fc3f-48ef-a705-a69ae2c8e9ec",
|
||||
"name": "address",
|
||||
"displayName": "IP Address",
|
||||
"type" : "QString"
|
||||
},
|
||||
{
|
||||
"id": "4628c040-6bbb-43c9-b25f-ce3b22300e3b",
|
||||
"name": "port",
|
||||
"displayName": "Port",
|
||||
"type" : "int"
|
||||
},
|
||||
{
|
||||
"id": "8fd2a7d5-bb26-4f18-a488-5ab0779733f8",
|
||||
"name": "serialNumber",
|
||||
"displayName": "Serial number",
|
||||
"type" : "QString"
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "8092f387-5099-43e8-a7c4-7f0dd7b70fce",
|
||||
"name": "connected",
|
||||
"displayName": "Connected",
|
||||
"displayNameEvent": "Connected changed",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false
|
||||
},
|
||||
{
|
||||
"id": "2f650ae6-f3a5-4851-8449-1ba02c4864e5",
|
||||
"name": "mute",
|
||||
"displayName": "Mute",
|
||||
"displayNameEvent": "Mute changed",
|
||||
"displayNameAction": "Set mute",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "a444bb7c-7266-4c7e-874a-eb04bb91b9cf",
|
||||
"name": "volume",
|
||||
"displayName": "Volume",
|
||||
"displayNameEvent": "Volume changed",
|
||||
"displayNameAction": "Set volume",
|
||||
"type": "int",
|
||||
"defaultValue": 50,
|
||||
"minValue": 0,
|
||||
"maxValue": 100,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "43f552c7-7dfe-4358-bebd-ab558191cdfc",
|
||||
"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": "5636c21a-f14b-472c-8486-177543f6adfb",
|
||||
"name": "shuffle",
|
||||
"displayName": "Shuffle",
|
||||
"displayNameEvent": "Shuffle changed",
|
||||
"displayNameAction": "Set shuffle",
|
||||
"type": "bool",
|
||||
"defaultValue": false,
|
||||
"cached": false,
|
||||
"writable": true
|
||||
},
|
||||
{
|
||||
"id": "b4a572b1-6120-43e8-9a6c-18d099c8b162",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"id": "604e4995-ee1a-44fc-bfcb-ca0e861710bd",
|
||||
"name": "source",
|
||||
"displayName": "Source",
|
||||
"displayNameEvent": "Source changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "8c5372f1-3dde-4984-9955-9a436a29e8e3",
|
||||
"name": "artist",
|
||||
"displayName": "Artist",
|
||||
"displayNameEvent": "Artist changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "d2a2db24-5855-40cd-a043-6f67e43acc61",
|
||||
"name": "collection",
|
||||
"displayName": "Album",
|
||||
"displayNameEvent": "Album changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "6204ec9d-6aab-4fd3-8911-fdaa462c19a8",
|
||||
"name": "title",
|
||||
"displayName": "Title",
|
||||
"displayNameEvent": "Title changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "918bfeed-bf96-4034-85d6-9f4cff35fd00",
|
||||
"name": "artwork",
|
||||
"displayName": "Artwork",
|
||||
"displayNameEvent": "Artwork changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "69757ef3-173f-499c-9304-4252de3588c6",
|
||||
"name": "group",
|
||||
"displayName": "Group",
|
||||
"displayNameEvent": "Group changed",
|
||||
"type": "QString",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"id": "e5222e93-fa14-49de-950f-2f605ce8927b",
|
||||
"name": "playerType",
|
||||
"displayName": "Player type",
|
||||
"displayNameEvent": "Player type changed",
|
||||
"possibleValues": [
|
||||
"audio",
|
||||
"video"
|
||||
],
|
||||
"type": "QString",
|
||||
"defaultValue": "audio"
|
||||
}
|
||||
],
|
||||
"actionTypes": [
|
||||
{
|
||||
"id": "864a5bcc-71e1-4d7f-8f2e-3c4222d5d988",
|
||||
"name": "skipBack",
|
||||
"displayName": "Skip back"
|
||||
},
|
||||
{
|
||||
"id": "2526ec6d-1c21-4f73-97f1-973a5f05b626",
|
||||
"name": "stop",
|
||||
"displayName": "Stop"
|
||||
},
|
||||
{
|
||||
"id": "253eb62f-d50d-4667-8213-8632de178aa3",
|
||||
"name": "play",
|
||||
"displayName": "Play"
|
||||
},
|
||||
{
|
||||
"id": "92446566-8c32-4ee2-9498-d9dd9333a75d",
|
||||
"name": "pause",
|
||||
"displayName": "Pause"
|
||||
},
|
||||
{
|
||||
"id": "30930095-6f97-48ef-8bbf-597d734f0751",
|
||||
"name": "skipNext",
|
||||
"displayName": "Skip next"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
bluos/meta.json
Normal file
13
bluos/meta.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"title": "BluOS",
|
||||
"tagline": "Control audio devices based on BluOS.",
|
||||
"icon": "blusound.png",
|
||||
"stability": "consumer",
|
||||
"offline": true,
|
||||
"technologies": [
|
||||
"network"
|
||||
],
|
||||
"categories": [
|
||||
"multimedia"
|
||||
]
|
||||
}
|
||||
295
bluos/translations/71dd25b3-37ef-4b27-abca-24989fa38c61-de.ts
Normal file
295
bluos/translations/71dd25b3-37ef-4b27-abca-24989fa38c61-de.ts
Normal file
@ -0,0 +1,295 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="de">
|
||||
<context>
|
||||
<name>BluOS</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="77"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="80"/>
|
||||
<source>Album</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: collection, ID: {d2a2db24-5855-40cd-a043-6f67e43acc61})
|
||||
----------
|
||||
The name of the StateType ({d2a2db24-5855-40cd-a043-6f67e43acc61}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Album</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="83"/>
|
||||
<source>Album changed</source>
|
||||
<extracomment>The name of the EventType ({d2a2db24-5855-40cd-a043-6f67e43acc61}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Album geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="86"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="89"/>
|
||||
<source>Artist</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: artist, ID: {8c5372f1-3dde-4984-9955-9a436a29e8e3})
|
||||
----------
|
||||
The name of the StateType ({8c5372f1-3dde-4984-9955-9a436a29e8e3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Künstler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="92"/>
|
||||
<source>Artist changed</source>
|
||||
<extracomment>The name of the EventType ({8c5372f1-3dde-4984-9955-9a436a29e8e3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Künstler geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="95"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="98"/>
|
||||
<source>Artwork</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: artwork, ID: {918bfeed-bf96-4034-85d6-9f4cff35fd00})
|
||||
----------
|
||||
The name of the StateType ({918bfeed-bf96-4034-85d6-9f4cff35fd00}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Artwork</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="101"/>
|
||||
<source>Artwork changed</source>
|
||||
<extracomment>The name of the EventType ({918bfeed-bf96-4034-85d6-9f4cff35fd00}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Artwork geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="104"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="107"/>
|
||||
<source>BluOS</source>
|
||||
<extracomment>The name of the vendor ({39a492e9-e497-4b43-94d4-970eb9913b96})
|
||||
----------
|
||||
The name of the plugin BluOS ({71dd25b3-37ef-4b27-abca-24989fa38c61})</extracomment>
|
||||
<translation>BluOS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="110"/>
|
||||
<source>BluOS player</source>
|
||||
<extracomment>The name of the ThingClass ({406adcbc-1e7d-4e41-ae2a-f87b6bafd13d})</extracomment>
|
||||
<translation>BluOS Player</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="113"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="116"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: connected, ID: {8092f387-5099-43e8-a7c4-7f0dd7b70fce})
|
||||
----------
|
||||
The name of the StateType ({8092f387-5099-43e8-a7c4-7f0dd7b70fce}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Verbunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="119"/>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({8092f387-5099-43e8-a7c4-7f0dd7b70fce}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Verbunden geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="122"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="125"/>
|
||||
<source>Group</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: group, ID: {69757ef3-173f-499c-9304-4252de3588c6})
|
||||
----------
|
||||
The name of the StateType ({69757ef3-173f-499c-9304-4252de3588c6}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Gruppe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="128"/>
|
||||
<source>Group changed</source>
|
||||
<extracomment>The name of the EventType ({69757ef3-173f-499c-9304-4252de3588c6}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Gruppe geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="131"/>
|
||||
<source>IP Address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {833f99cc-fc3f-48ef-a705-a69ae2c8e9ec})</extracomment>
|
||||
<translation>IP-Adresse</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="134"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="137"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="140"/>
|
||||
<source>Mute</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: mute, ID: {2f650ae6-f3a5-4851-8449-1ba02c4864e5})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: mute, ID: {2f650ae6-f3a5-4851-8449-1ba02c4864e5})
|
||||
----------
|
||||
The name of the StateType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Stumm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="143"/>
|
||||
<source>Mute changed</source>
|
||||
<extracomment>The name of the EventType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Stumm geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="146"/>
|
||||
<source>Pause</source>
|
||||
<extracomment>The name of the ActionType ({92446566-8c32-4ee2-9498-d9dd9333a75d}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Pause</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="149"/>
|
||||
<source>Play</source>
|
||||
<extracomment>The name of the ActionType ({253eb62f-d50d-4667-8213-8632de178aa3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Play</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="152"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="155"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="158"/>
|
||||
<source>Playback status</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: playbackStatus, ID: {43f552c7-7dfe-4358-bebd-ab558191cdfc})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: playbackStatus, ID: {43f552c7-7dfe-4358-bebd-ab558191cdfc})
|
||||
----------
|
||||
The name of the StateType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Playbackstatus</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="161"/>
|
||||
<source>Playback status changed</source>
|
||||
<extracomment>The name of the EventType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Playbackstatus geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="164"/>
|
||||
<source>Port</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {4628c040-6bbb-43c9-b25f-ce3b22300e3b})</extracomment>
|
||||
<translation>Port</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="167"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="170"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="173"/>
|
||||
<source>Repeat mode</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: repeat, ID: {b4a572b1-6120-43e8-9a6c-18d099c8b162})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: repeat, ID: {b4a572b1-6120-43e8-9a6c-18d099c8b162})
|
||||
----------
|
||||
The name of the StateType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Wiederholungsmodus</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="176"/>
|
||||
<source>Repeat mode changed</source>
|
||||
<extracomment>The name of the EventType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Wiederholungsmodus geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="179"/>
|
||||
<source>Serial number</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {8fd2a7d5-bb26-4f18-a488-5ab0779733f8})</extracomment>
|
||||
<translation>Seriennummer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="182"/>
|
||||
<source>Set mute</source>
|
||||
<extracomment>The name of the ActionType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Setze stumm</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="185"/>
|
||||
<source>Set playback status</source>
|
||||
<extracomment>The name of the ActionType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Setze Playbackstatus</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="188"/>
|
||||
<source>Set repeat mode</source>
|
||||
<extracomment>The name of the ActionType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Setze Wiederholungsmodus</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="191"/>
|
||||
<source>Set shuffle</source>
|
||||
<extracomment>The name of the ActionType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Setze Zufallswiedergabe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="194"/>
|
||||
<source>Set volume</source>
|
||||
<extracomment>The name of the ActionType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Setze Lautstärke</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="197"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="200"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="203"/>
|
||||
<source>Shuffle</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: shuffle, ID: {5636c21a-f14b-472c-8486-177543f6adfb})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: shuffle, ID: {5636c21a-f14b-472c-8486-177543f6adfb})
|
||||
----------
|
||||
The name of the StateType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Zufallswiedergabe</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="206"/>
|
||||
<source>Shuffle changed</source>
|
||||
<extracomment>The name of the EventType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Zufallswiedergabe geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="209"/>
|
||||
<source>Skip back</source>
|
||||
<extracomment>The name of the ActionType ({864a5bcc-71e1-4d7f-8f2e-3c4222d5d988}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Vorheriges</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="212"/>
|
||||
<source>Skip next</source>
|
||||
<extracomment>The name of the ActionType ({30930095-6f97-48ef-8bbf-597d734f0751}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Nächstes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="215"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="218"/>
|
||||
<source>Source</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: source, ID: {604e4995-ee1a-44fc-bfcb-ca0e861710bd})
|
||||
----------
|
||||
The name of the StateType ({604e4995-ee1a-44fc-bfcb-ca0e861710bd}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Quelle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="221"/>
|
||||
<source>Source changed</source>
|
||||
<extracomment>The name of the EventType ({604e4995-ee1a-44fc-bfcb-ca0e861710bd}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Quelle geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="224"/>
|
||||
<source>Stop</source>
|
||||
<extracomment>The name of the ActionType ({2526ec6d-1c21-4f73-97f1-973a5f05b626}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Stopp</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="227"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="230"/>
|
||||
<source>Title</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: title, ID: {6204ec9d-6aab-4fd3-8911-fdaa462c19a8})
|
||||
----------
|
||||
The name of the StateType ({6204ec9d-6aab-4fd3-8911-fdaa462c19a8}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Titel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="233"/>
|
||||
<source>Title changed</source>
|
||||
<extracomment>The name of the EventType ({6204ec9d-6aab-4fd3-8911-fdaa462c19a8}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Titel geändert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="236"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="239"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="242"/>
|
||||
<source>Volume</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: volume, ID: {a444bb7c-7266-4c7e-874a-eb04bb91b9cf})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: volume, ID: {a444bb7c-7266-4c7e-874a-eb04bb91b9cf})
|
||||
----------
|
||||
The name of the StateType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Lautstärke</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="245"/>
|
||||
<source>Volume changed</source>
|
||||
<extracomment>The name of the EventType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation>Lautstärke geändert</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
295
bluos/translations/71dd25b3-37ef-4b27-abca-24989fa38c61-en_US.ts
Normal file
295
bluos/translations/71dd25b3-37ef-4b27-abca-24989fa38c61-en_US.ts
Normal file
@ -0,0 +1,295 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>BluOS</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="77"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="80"/>
|
||||
<source>Album</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: collection, ID: {d2a2db24-5855-40cd-a043-6f67e43acc61})
|
||||
----------
|
||||
The name of the StateType ({d2a2db24-5855-40cd-a043-6f67e43acc61}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="83"/>
|
||||
<source>Album changed</source>
|
||||
<extracomment>The name of the EventType ({d2a2db24-5855-40cd-a043-6f67e43acc61}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="86"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="89"/>
|
||||
<source>Artist</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: artist, ID: {8c5372f1-3dde-4984-9955-9a436a29e8e3})
|
||||
----------
|
||||
The name of the StateType ({8c5372f1-3dde-4984-9955-9a436a29e8e3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="92"/>
|
||||
<source>Artist changed</source>
|
||||
<extracomment>The name of the EventType ({8c5372f1-3dde-4984-9955-9a436a29e8e3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="95"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="98"/>
|
||||
<source>Artwork</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: artwork, ID: {918bfeed-bf96-4034-85d6-9f4cff35fd00})
|
||||
----------
|
||||
The name of the StateType ({918bfeed-bf96-4034-85d6-9f4cff35fd00}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="101"/>
|
||||
<source>Artwork changed</source>
|
||||
<extracomment>The name of the EventType ({918bfeed-bf96-4034-85d6-9f4cff35fd00}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="104"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="107"/>
|
||||
<source>BluOS</source>
|
||||
<extracomment>The name of the vendor ({39a492e9-e497-4b43-94d4-970eb9913b96})
|
||||
----------
|
||||
The name of the plugin BluOS ({71dd25b3-37ef-4b27-abca-24989fa38c61})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="110"/>
|
||||
<source>BluOS player</source>
|
||||
<extracomment>The name of the ThingClass ({406adcbc-1e7d-4e41-ae2a-f87b6bafd13d})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="113"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="116"/>
|
||||
<source>Connected</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: connected, ID: {8092f387-5099-43e8-a7c4-7f0dd7b70fce})
|
||||
----------
|
||||
The name of the StateType ({8092f387-5099-43e8-a7c4-7f0dd7b70fce}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="119"/>
|
||||
<source>Connected changed</source>
|
||||
<extracomment>The name of the EventType ({8092f387-5099-43e8-a7c4-7f0dd7b70fce}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="122"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="125"/>
|
||||
<source>Group</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: group, ID: {69757ef3-173f-499c-9304-4252de3588c6})
|
||||
----------
|
||||
The name of the StateType ({69757ef3-173f-499c-9304-4252de3588c6}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="128"/>
|
||||
<source>Group changed</source>
|
||||
<extracomment>The name of the EventType ({69757ef3-173f-499c-9304-4252de3588c6}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="131"/>
|
||||
<source>IP Address</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {833f99cc-fc3f-48ef-a705-a69ae2c8e9ec})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="134"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="137"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="140"/>
|
||||
<source>Mute</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: mute, ID: {2f650ae6-f3a5-4851-8449-1ba02c4864e5})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: mute, ID: {2f650ae6-f3a5-4851-8449-1ba02c4864e5})
|
||||
----------
|
||||
The name of the StateType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="143"/>
|
||||
<source>Mute changed</source>
|
||||
<extracomment>The name of the EventType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="146"/>
|
||||
<source>Pause</source>
|
||||
<extracomment>The name of the ActionType ({92446566-8c32-4ee2-9498-d9dd9333a75d}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="149"/>
|
||||
<source>Play</source>
|
||||
<extracomment>The name of the ActionType ({253eb62f-d50d-4667-8213-8632de178aa3}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="152"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="155"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="158"/>
|
||||
<source>Playback status</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: playbackStatus, ID: {43f552c7-7dfe-4358-bebd-ab558191cdfc})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: playbackStatus, ID: {43f552c7-7dfe-4358-bebd-ab558191cdfc})
|
||||
----------
|
||||
The name of the StateType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="161"/>
|
||||
<source>Playback status changed</source>
|
||||
<extracomment>The name of the EventType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="164"/>
|
||||
<source>Port</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {4628c040-6bbb-43c9-b25f-ce3b22300e3b})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="167"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="170"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="173"/>
|
||||
<source>Repeat mode</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: repeat, ID: {b4a572b1-6120-43e8-9a6c-18d099c8b162})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: repeat, ID: {b4a572b1-6120-43e8-9a6c-18d099c8b162})
|
||||
----------
|
||||
The name of the StateType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="176"/>
|
||||
<source>Repeat mode changed</source>
|
||||
<extracomment>The name of the EventType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="179"/>
|
||||
<source>Serial number</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, Type: thing, ID: {8fd2a7d5-bb26-4f18-a488-5ab0779733f8})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="182"/>
|
||||
<source>Set mute</source>
|
||||
<extracomment>The name of the ActionType ({2f650ae6-f3a5-4851-8449-1ba02c4864e5}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="185"/>
|
||||
<source>Set playback status</source>
|
||||
<extracomment>The name of the ActionType ({43f552c7-7dfe-4358-bebd-ab558191cdfc}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="188"/>
|
||||
<source>Set repeat mode</source>
|
||||
<extracomment>The name of the ActionType ({b4a572b1-6120-43e8-9a6c-18d099c8b162}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="191"/>
|
||||
<source>Set shuffle</source>
|
||||
<extracomment>The name of the ActionType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="194"/>
|
||||
<source>Set volume</source>
|
||||
<extracomment>The name of the ActionType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="197"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="200"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="203"/>
|
||||
<source>Shuffle</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: shuffle, ID: {5636c21a-f14b-472c-8486-177543f6adfb})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: shuffle, ID: {5636c21a-f14b-472c-8486-177543f6adfb})
|
||||
----------
|
||||
The name of the StateType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="206"/>
|
||||
<source>Shuffle changed</source>
|
||||
<extracomment>The name of the EventType ({5636c21a-f14b-472c-8486-177543f6adfb}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="209"/>
|
||||
<source>Skip back</source>
|
||||
<extracomment>The name of the ActionType ({864a5bcc-71e1-4d7f-8f2e-3c4222d5d988}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="212"/>
|
||||
<source>Skip next</source>
|
||||
<extracomment>The name of the ActionType ({30930095-6f97-48ef-8bbf-597d734f0751}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="215"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="218"/>
|
||||
<source>Source</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: source, ID: {604e4995-ee1a-44fc-bfcb-ca0e861710bd})
|
||||
----------
|
||||
The name of the StateType ({604e4995-ee1a-44fc-bfcb-ca0e861710bd}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="221"/>
|
||||
<source>Source changed</source>
|
||||
<extracomment>The name of the EventType ({604e4995-ee1a-44fc-bfcb-ca0e861710bd}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="224"/>
|
||||
<source>Stop</source>
|
||||
<extracomment>The name of the ActionType ({2526ec6d-1c21-4f73-97f1-973a5f05b626}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="227"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="230"/>
|
||||
<source>Title</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, EventType: title, ID: {6204ec9d-6aab-4fd3-8911-fdaa462c19a8})
|
||||
----------
|
||||
The name of the StateType ({6204ec9d-6aab-4fd3-8911-fdaa462c19a8}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="233"/>
|
||||
<source>Title changed</source>
|
||||
<extracomment>The name of the EventType ({6204ec9d-6aab-4fd3-8911-fdaa462c19a8}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="236"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="239"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="242"/>
|
||||
<source>Volume</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: bluosPlayer, ActionType: volume, ID: {a444bb7c-7266-4c7e-874a-eb04bb91b9cf})
|
||||
----------
|
||||
The name of the ParamType (ThingClass: bluosPlayer, EventType: volume, ID: {a444bb7c-7266-4c7e-874a-eb04bb91b9cf})
|
||||
----------
|
||||
The name of the StateType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/bluos/plugininfo.h" line="245"/>
|
||||
<source>Volume changed</source>
|
||||
<extracomment>The name of the EventType ({a444bb7c-7266-4c7e-874a-eb04bb91b9cf}) of ThingClass bluosPlayer</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
15
debian/control
vendored
15
debian/control
vendored
@ -88,6 +88,21 @@ Description: nymea.io plugin for awattar
|
||||
This package will install the nymea.io plugin for awattar
|
||||
|
||||
|
||||
Package: nymea-plugin-bluos
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
nymea-plugins-translations,
|
||||
Description: nymea.io plugin for bluos
|
||||
The nymea daemon is a plugin based IoT (Internet of Things) server. The
|
||||
server works like a translator for devices, things and services and
|
||||
allows them to interact.
|
||||
With the powerful rule engine you are able to connect any device available
|
||||
in the system and create individual scenes and behaviors for your environment.
|
||||
.
|
||||
This package will install the nymea.io plugin for bluos
|
||||
|
||||
|
||||
Package: nymea-plugin-boblight
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
||||
1
debian/nymea-plugin-bluos.install.in
vendored
Normal file
1
debian/nymea-plugin-bluos.install.in
vendored
Normal file
@ -0,0 +1 @@
|
||||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginbluos.so
|
||||
@ -5,6 +5,7 @@ PLUGIN_DIRS = \
|
||||
aqi \
|
||||
avahimonitor \
|
||||
awattar \
|
||||
bluos \
|
||||
boblight \
|
||||
bose \
|
||||
coinmarketcap \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user