kodi: Add Qt6 support

This commit is contained in:
Simon Stürz 2025-08-08 14:12:38 +02:00
parent ecd29be68e
commit c31980a4cd
9 changed files with 71 additions and 76 deletions

View File

@ -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());

View File

@ -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);

View File

@ -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 &params)
{
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 &params)
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();

View File

@ -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;

View File

@ -1,8 +1,6 @@
include(../plugins.pri)
QT += network
TARGET = $$qtLibraryTarget(nymea_integrationpluginkodi)
QT *= gui network
SOURCES += \
integrationpluginkodi.cpp \

View File

@ -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());

View File

@ -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

View File

@ -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;

View File

@ -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: