kodi: Add Qt6 support
This commit is contained in:
parent
ecd29be68e
commit
c31980a4cd
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -29,13 +29,13 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "integrationpluginkodi.h"
|
||||
#include "integrations/thing.h"
|
||||
#include "plugininfo.h"
|
||||
#include "network/upnp/upnpdiscovery.h"
|
||||
#include "platform/platformzeroconfcontroller.h"
|
||||
#include "network/zeroconf/zeroconfservicebrowser.h"
|
||||
#include "network/zeroconf/zeroconfserviceentry.h"
|
||||
#include "network/networkaccessmanager.h"
|
||||
|
||||
#include <integrations/thing.h>
|
||||
#include <platform/platformzeroconfcontroller.h>
|
||||
#include <network/zeroconf/zeroconfservicebrowser.h>
|
||||
#include <network/zeroconf/zeroconfserviceentry.h>
|
||||
#include <network/networkaccessmanager.h>
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
@ -213,7 +213,7 @@ void IntegrationPluginKodi::discoverThings(ThingDiscoveryInfo *info)
|
||||
|
||||
foreach (const ZeroConfServiceEntry avahiEntry, m_serviceBrowser->serviceEntries()) {
|
||||
|
||||
QUuid uuid = avahiEntry.txt("uuid");
|
||||
QUuid uuid(avahiEntry.txt("uuid"));
|
||||
if (descriptors.contains(uuid)) {
|
||||
// Might appear multiple times, IPv4 and IPv6
|
||||
continue;
|
||||
@ -312,7 +312,7 @@ void IntegrationPluginKodi::executeAction(ThingActionInfo *info)
|
||||
commandId = kodi->setRepeat("off");
|
||||
}
|
||||
} else {
|
||||
qWarning(dcKodi()) << "Unhandled action type" << action.actionTypeId();
|
||||
qCWarning(dcKodi()) << "Unhandled action type" << action.actionTypeId();
|
||||
return info->finish(Thing::ThingErrorActionTypeNotFound);
|
||||
}
|
||||
|
||||
@ -385,7 +385,7 @@ IntegrationPluginKodi::KodiHostInfo IntegrationPluginKodi::resolve(Thing *thing)
|
||||
continue;
|
||||
}
|
||||
|
||||
QUuid entryUuid = entry.txt("uuid");
|
||||
QUuid entryUuid(entry.txt("uuid"));
|
||||
if (entryUuid != uuid) {
|
||||
continue;
|
||||
}
|
||||
@ -405,7 +405,7 @@ IntegrationPluginKodi::KodiHostInfo IntegrationPluginKodi::resolve(Thing *thing)
|
||||
if (ret.address.isNull()) {
|
||||
if (pluginStorage()->childGroups().contains(thing->id().toString())) {
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
ret.address = pluginStorage()->value("address").toString();
|
||||
ret.address = QHostAddress(pluginStorage()->value("address").toString());
|
||||
ret.rpcPort = pluginStorage()->value("rpcPort").toUInt();
|
||||
ret.httpPort = pluginStorage()->value("httpPort").toUInt();
|
||||
pluginStorage()->endGroup();
|
||||
@ -427,7 +427,6 @@ void IntegrationPluginKodi::onConnectionChanged(bool connected)
|
||||
|
||||
thing->setStateValue(kodiConnectedStateTypeId, connected);
|
||||
|
||||
|
||||
if (connected) {
|
||||
pluginStorage()->beginGroup(thing->id().toString());
|
||||
pluginStorage()->setValue("address", kodi->hostAddress().toString());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -31,8 +31,9 @@
|
||||
#ifndef INTEGRATIONPLUGINKODI_H
|
||||
#define INTEGRATIONPLUGINKODI_H
|
||||
|
||||
#include "integrations/integrationplugin.h"
|
||||
#include "plugintimer.h"
|
||||
#include <integrations/integrationplugin.h>
|
||||
#include <plugintimer.h>
|
||||
|
||||
#include "kodi.h"
|
||||
|
||||
#include <QHash>
|
||||
@ -74,13 +75,13 @@ private:
|
||||
|
||||
private:
|
||||
PluginTimer *m_pluginTimer = nullptr;
|
||||
QHash<Thing*, Kodi*> m_kodis;
|
||||
QHash<Thing *, Kodi *> m_kodis;
|
||||
ZeroConfServiceBrowser *m_serviceBrowser = nullptr;
|
||||
ZeroConfServiceBrowser *m_httpServiceBrowser = nullptr;
|
||||
|
||||
QHash<int, ThingActionInfo*> m_pendingActions;
|
||||
QHash<int, BrowserActionInfo*> m_pendingBrowserActions;
|
||||
QHash<int, BrowserItemActionInfo*> m_pendingBrowserItemActions;
|
||||
QHash<int, ThingActionInfo *> m_pendingActions;
|
||||
QHash<int, BrowserActionInfo *> m_pendingBrowserActions;
|
||||
QHash<int, BrowserItemActionInfo *> m_pendingBrowserItemActions;
|
||||
|
||||
private slots:
|
||||
void onConnectionChanged(bool connected);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -29,10 +29,12 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "kodi.h"
|
||||
#include <QDebug>
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <QRegularExpression>
|
||||
|
||||
Kodi::Kodi(const QHostAddress &hostAddress, int port, int httpPort, QObject *parent) :
|
||||
QObject(parent),
|
||||
@ -47,7 +49,6 @@ Kodi::Kodi(const QHostAddress &hostAddress, int port, int httpPort, QObject *par
|
||||
connect(m_jsonHandler, &KodiJsonHandler::notificationReceived, this, &Kodi::processNotification);
|
||||
connect(m_jsonHandler, &KodiJsonHandler::replyReceived, this, &Kodi::processResponse);
|
||||
|
||||
|
||||
// Init FS
|
||||
m_virtualFs = new VirtualFsNode(BrowserItem());
|
||||
|
||||
@ -172,8 +173,6 @@ Kodi::Kodi(const QHostAddress &hostAddress, int port, int httpPort, QObject *par
|
||||
musicAddons->getParams.insert("sort", sort);
|
||||
musicAddons->getParams.insert("properties", properties);
|
||||
addons->addChild(musicAddons);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Kodi::~Kodi()
|
||||
@ -362,7 +361,7 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("artist:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^artist:"));
|
||||
idString.remove(QRegularExpression("^artist:"));
|
||||
QVariantMap filter;
|
||||
filter.insert("artistid", idString.toInt());
|
||||
QVariantMap params;
|
||||
@ -378,7 +377,7 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("album:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^album:"));
|
||||
idString.remove(QRegularExpression("^album:"));
|
||||
QVariantMap filter;
|
||||
filter.insert("albumid", idString.toInt());
|
||||
QVariantMap params;
|
||||
@ -396,7 +395,7 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("tvshow:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^tvshow:"));
|
||||
idString.remove(QRegularExpression("^tvshow:"));
|
||||
QVariantMap params;
|
||||
params.insert("tvshowid", idString.toInt());
|
||||
QVariantList properties;
|
||||
@ -412,9 +411,9 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("season:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^season:"));
|
||||
idString.remove(QRegularExpression("^season:"));
|
||||
int seasonId = idString.left(idString.indexOf(",")).toInt();
|
||||
idString.remove(QRegExp("^[0-9]*,tvshow:"));
|
||||
idString.remove(QRegularExpression("^[0-9]*,tvshow:"));
|
||||
int tvShowId = idString.toInt();
|
||||
QVariantMap params;
|
||||
params.insert("tvshowid", tvShowId);
|
||||
@ -432,7 +431,7 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("addon:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^addon:"));
|
||||
idString.remove(QRegularExpression("^addon:"));
|
||||
QVariantMap params;
|
||||
params.insert("directory", "plugin://" + idString);
|
||||
// QVariantList properties;
|
||||
@ -447,7 +446,7 @@ void Kodi::browse(BrowseResult *result)
|
||||
|
||||
if (result->itemId().startsWith("file:")) {
|
||||
QString idString = result->itemId();
|
||||
idString.remove(QRegExp("^file:"));
|
||||
idString.remove(QRegularExpression("^file:"));
|
||||
QVariantMap params;
|
||||
params.insert("directory", idString);
|
||||
params.insert("properties", properties);
|
||||
@ -468,19 +467,19 @@ void Kodi::browserItem(BrowserItemResult *result)
|
||||
QString method;
|
||||
QVariantMap params;
|
||||
if (idString.startsWith("song:")) {
|
||||
idString.remove(QRegExp("^song:"));
|
||||
idString.remove(QRegularExpression("^song:"));
|
||||
params.insert("songid", idString.toInt());
|
||||
method = "AudioLibrary.GetSongDetails";
|
||||
} else if (idString.startsWith("movie:")) {
|
||||
idString.remove(QRegExp("^movie:"));
|
||||
idString.remove(QRegularExpression("^movie:"));
|
||||
params.insert("movieid", idString.toInt());
|
||||
method = "VideoLibrary.GetMovieDetails";
|
||||
} else if (idString.startsWith("episode:")) {
|
||||
idString.remove(QRegExp("^episode:"));
|
||||
idString.remove(QRegularExpression("^episode:"));
|
||||
params.insert("episodeid", idString.toInt());
|
||||
method = "VideoLibrary.GetEpisodeDetails";
|
||||
} else if (idString.startsWith("musicvideo:")) {
|
||||
idString.remove(QRegExp("^musicvideo:"));
|
||||
idString.remove(QRegularExpression("^musicvideo:"));
|
||||
params.insert("musicvideoid", idString.toInt());
|
||||
method = "VideoLibrary.GetMusicVideoDetails";
|
||||
} else {
|
||||
@ -499,11 +498,11 @@ int Kodi::launchBrowserItem(const QString &itemId)
|
||||
|
||||
QString idString = itemId;
|
||||
if (idString.startsWith("song:")) {
|
||||
idString.remove(QRegExp("^song:"));
|
||||
idString.remove(QRegularExpression("^song:"));
|
||||
int idx = idString.indexOf(",album:");
|
||||
if (idx > 0) {
|
||||
int position = idString.left(idx).toInt();
|
||||
idString.remove(QRegExp("^[0-9]*,album:"));
|
||||
idString.remove(QRegularExpression("^[0-9]*,album:"));
|
||||
int albumId = idString.toInt();
|
||||
|
||||
QVariantMap params;
|
||||
@ -522,13 +521,13 @@ int Kodi::launchBrowserItem(const QString &itemId)
|
||||
playlistItem.insert("songid", idString.toInt());
|
||||
}
|
||||
} else if (idString.startsWith("movie:")) {
|
||||
idString.remove(QRegExp("^movie:"));
|
||||
idString.remove(QRegularExpression("^movie:"));
|
||||
playlistItem.insert("movieid", idString.toInt());
|
||||
} else if (idString.startsWith("episode:")) {
|
||||
idString.remove(QRegExp("^episode:"));
|
||||
idString.remove(QRegularExpression("^episode:"));
|
||||
playlistItem.insert("episodeid", idString.toInt());
|
||||
} else if (idString.startsWith("file:")) {
|
||||
idString.remove(QRegExp("^file:"));
|
||||
idString.remove(QRegularExpression("^file:"));
|
||||
playlistItem.insert("file", idString);
|
||||
} else {
|
||||
qCWarning(dcKodi()) << "Unhandled launchBrowserItem request!" << itemId;
|
||||
@ -585,7 +584,7 @@ void Kodi::onVolumeChanged(const int &volume, const bool &muted)
|
||||
|
||||
void Kodi::onUpdateFinished(const QVariantMap &data)
|
||||
{
|
||||
qCDebug(dcKodi()) << "update finished:" << data;
|
||||
qCDebug(dcKodi()) << "Update finished:" << data;
|
||||
if (data.contains("volume")) {
|
||||
m_volume = data.value("volume").toInt();
|
||||
}
|
||||
@ -597,7 +596,7 @@ void Kodi::onUpdateFinished(const QVariantMap &data)
|
||||
|
||||
void Kodi::activePlayersChanged(const QVariantList &data)
|
||||
{
|
||||
qCDebug(dcKodi()) << "active players changed" << data.count() << data;
|
||||
qCDebug(dcKodi()) << "Active players changed" << data.count() << data;
|
||||
m_activePlayerCount = data.count();
|
||||
if (m_activePlayerCount == 0) {
|
||||
onPlaybackStatusChanged("Stopped");
|
||||
@ -612,7 +611,7 @@ void Kodi::activePlayersChanged(const QVariantList &data)
|
||||
|
||||
void Kodi::playerPropertiesReceived(const QVariantMap &properties)
|
||||
{
|
||||
qCDebug(dcKodi()) << "player props received" << properties;
|
||||
qCDebug(dcKodi()) << "Player props received" << properties;
|
||||
|
||||
if (m_activePlayerCount > 0) {
|
||||
if (properties.value("speed").toDouble() > 0) {
|
||||
@ -657,7 +656,7 @@ void Kodi::mediaMetaDataReceived(const QVariantMap &data)
|
||||
if (artwork.isEmpty()) {
|
||||
artwork = item.value("fanart").toString();
|
||||
}
|
||||
qCDebug(dcKodi) << "title:" << title << artwork;
|
||||
qCDebug(dcKodi) << "Title:" << title << artwork;
|
||||
emit mediaMetadataChanged(title, artist, collection, artwork);
|
||||
}
|
||||
|
||||
@ -673,7 +672,7 @@ void Kodi::onPlaybackStatusChanged(const QString &playbackState)
|
||||
|
||||
void Kodi::processNotification(const QString &method, const QVariantMap ¶ms)
|
||||
{
|
||||
qCDebug(dcKodi) << "got notification" << method << params;
|
||||
qCDebug(dcKodi) << "Got notification" << method << params;
|
||||
|
||||
if (method == "Application.OnVolumeChanged") {
|
||||
QVariantMap data = params.value("data").toMap();
|
||||
@ -693,7 +692,7 @@ void Kodi::processNotification(const QString &method, const QVariantMap ¶ms)
|
||||
void Kodi::processResponse(int id, const QString &method, const QVariantMap &response)
|
||||
{
|
||||
|
||||
qCDebug(dcKodi) << "response received:" << method << response;
|
||||
qCDebug(dcKodi) << "Response received:" << method << response;
|
||||
|
||||
if (response.contains("error")) {
|
||||
qCWarning(dcKodi) << "got error response for request " << method << ":" << response.value("error").toMap().value("message").toString();
|
||||
|
||||
17
kodi/kodi.h
17
kodi/kodi.h
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -37,11 +37,9 @@
|
||||
#include "kodiconnection.h"
|
||||
#include "kodijsonhandler.h"
|
||||
|
||||
#include "types/browseritem.h"
|
||||
#include "types/browseritemaction.h"
|
||||
#include "integrations/thing.h"
|
||||
#include "integrations/browseresult.h"
|
||||
#include "integrations/browseritemresult.h"
|
||||
#include <types/browseritem.h>
|
||||
#include <integrations/browseresult.h>
|
||||
#include <integrations/browseritemresult.h>
|
||||
|
||||
class Kodi : public QObject
|
||||
{
|
||||
@ -120,10 +118,10 @@ private:
|
||||
QString prepareThumbnail(const QString &thumbnail);
|
||||
|
||||
private:
|
||||
KodiConnection *m_connection;
|
||||
KodiConnection *m_connection = nullptr;
|
||||
int m_httpPort;
|
||||
KodiJsonHandler *m_jsonHandler;
|
||||
bool m_muted;
|
||||
KodiJsonHandler *m_jsonHandler = nullptr;
|
||||
bool m_muted = false;
|
||||
int m_volume;
|
||||
int m_activePlayerCount = 0; // if it's > 0, there is something playing (either music or video or slideshow)
|
||||
int m_activePlayer = -1;
|
||||
@ -146,6 +144,7 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
VirtualFsNode* m_virtualFs = nullptr;
|
||||
|
||||
QHash<int, BrowseResult*> m_pendingBrowseRequests;
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
include(../plugins.pri)
|
||||
|
||||
QT += network
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_integrationpluginkodi)
|
||||
QT *= gui network
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginkodi.cpp \
|
||||
|
||||
@ -29,7 +29,6 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "kodiconnection.h"
|
||||
#include "kodijsonhandler.h"
|
||||
#include "extern-plugininfo.h"
|
||||
|
||||
#include <QPixmap>
|
||||
@ -44,7 +43,11 @@ KodiConnection::KodiConnection(const QHostAddress &hostAddress, int port, QObjec
|
||||
|
||||
connect(m_socket, &QTcpSocket::connected, this, &KodiConnection::onConnected);
|
||||
connect(m_socket, &QTcpSocket::disconnected, this, &KodiConnection::onDisconnected);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
|
||||
connect(m_socket, &QTcpSocket::errorOccurred, this, &KodiConnection::onError);
|
||||
#else
|
||||
connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
|
||||
#endif
|
||||
connect(m_socket, &QTcpSocket::readyRead, this, &KodiConnection::readData);
|
||||
}
|
||||
|
||||
@ -54,6 +57,7 @@ void KodiConnection::connectKodi()
|
||||
qCDebug(dcKodi) << "Aready connecting... skipping request";
|
||||
return;
|
||||
}
|
||||
|
||||
m_socket->connectToHost(m_hostAddress, m_port);
|
||||
}
|
||||
|
||||
@ -83,7 +87,7 @@ void KodiConnection::setPort(int port)
|
||||
}
|
||||
|
||||
|
||||
bool KodiConnection::connected()
|
||||
bool KodiConnection::connected() const
|
||||
{
|
||||
return m_connected;
|
||||
}
|
||||
@ -114,15 +118,15 @@ void KodiConnection::readData()
|
||||
QByteArray data = m_socket->readAll();
|
||||
|
||||
QStringList commandList = QString(data).split("}{");
|
||||
for(int i = 0; i < commandList.count(); ++i) {
|
||||
for (int i = 0; i < commandList.count(); ++i) {
|
||||
QString command = commandList.at(i);
|
||||
if(command.isEmpty()) {
|
||||
if (command.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if(i < commandList.count() - 1) {
|
||||
if (i < commandList.count() - 1) {
|
||||
command.append("}");
|
||||
}
|
||||
if(i > 0) {
|
||||
if (i > 0) {
|
||||
command.prepend("{");
|
||||
}
|
||||
emit dataReady(command.toUtf8());
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -51,14 +51,14 @@ public:
|
||||
int port() const;
|
||||
void setPort(int port);
|
||||
|
||||
bool connected();
|
||||
bool connected() const;
|
||||
|
||||
private:
|
||||
QTcpSocket *m_socket;
|
||||
QTcpSocket *m_socket = nullptr;
|
||||
|
||||
QHostAddress m_hostAddress;
|
||||
int m_port;
|
||||
bool m_connected;
|
||||
bool m_connected = false;
|
||||
|
||||
private slots:
|
||||
void onConnected();
|
||||
@ -73,8 +73,6 @@ signals:
|
||||
public slots:
|
||||
void sendData(const QByteArray &message);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // KODICONNECTION_H
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -37,7 +37,6 @@
|
||||
|
||||
#include "kodiconnection.h"
|
||||
#include "kodireply.h"
|
||||
#include "typeutils.h"
|
||||
|
||||
class KodiJsonHandler : public QObject
|
||||
{
|
||||
@ -55,7 +54,7 @@ private slots:
|
||||
void processResponse(const QByteArray &data);
|
||||
|
||||
private:
|
||||
KodiConnection *m_connection;
|
||||
KodiConnection *m_connection = nullptr;
|
||||
int m_id;
|
||||
QHash<int, KodiReply> m_replys;
|
||||
QByteArray m_dataBuffer;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* Copyright 2013 - 2020, nymea GmbH
|
||||
* Copyright 2013 - 2025, nymea GmbH
|
||||
* Contact: contact@nymea.io
|
||||
*
|
||||
* This file is part of nymea.
|
||||
@ -34,8 +34,6 @@
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "typeutils.h"
|
||||
|
||||
class KodiReply
|
||||
{
|
||||
public:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user