From c0e37de2fe2707b0012c290e1ec8e291e83b2608 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 19 Oct 2019 03:09:55 +0200 Subject: [PATCH 1/4] Kodi: Fix active player reading --- kodi/kodi.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/kodi/kodi.cpp b/kodi/kodi.cpp index 267549e6..163bd89b 100644 --- a/kodi/kodi.cpp +++ b/kodi/kodi.cpp @@ -563,7 +563,22 @@ void Kodi::activePlayersChanged(const QVariantList &data) } m_activePlayer = data.first().toMap().value("playerid").toInt(); qCDebug(dcKodi) << "Active Player changed:" << m_activePlayer << data.first().toMap().value("type").toString(); - emit activePlayerChanged(data.first().toMap().value("type").toString()); + if (data.first().toMap().contains("type")) { + emit activePlayerChanged(data.first().toMap().value("type").toString()); + } else { + // Player map doesn't contain type... sometimes... looks like a kodi bug... Assume 1 is video, 2 is music... + switch (m_activePlayer) { + case 1: + emit activePlayerChanged("video"); + break; + case 2: + emit activePlayerChanged("music"); + break; + case 3: + emit activePlayerChanged("picture"); + break; + } + } updatePlayerProperties(); } @@ -634,13 +649,12 @@ void Kodi::processNotification(const QString &method, const QVariantMap ¶ms) QVariantMap data = params.value("data").toMap(); onVolumeChanged(data.value("volume").toInt(), data.value("muted").toBool()); } else if (method == "Player.OnPlay" || method == "Player.OnResume") { - emit activePlayersChanged(QVariantList() << params.value("data").toMap().value("player")); onPlaybackStatusChanged("Playing"); + activePlayersChanged(QVariantList() << params.value("data").toMap().value("player")); } else if (method == "Player.OnPause") { emit playbackStatusChanged("Paused"); } else if (method == "Player.OnStop") { - emit playbackStatusChanged("Stopped"); - emit activePlayersChanged(QVariantList()); + activePlayersChanged(QVariantList()); } } From a60f78a35983e5379036b15d6a6b6bf33e408697 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 19 Oct 2019 03:42:38 +0200 Subject: [PATCH 2/4] more fixes --- kodi/kodi.cpp | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/kodi/kodi.cpp b/kodi/kodi.cpp index 163bd89b..ba1497c8 100644 --- a/kodi/kodi.cpp +++ b/kodi/kodi.cpp @@ -563,24 +563,9 @@ void Kodi::activePlayersChanged(const QVariantList &data) } m_activePlayer = data.first().toMap().value("playerid").toInt(); qCDebug(dcKodi) << "Active Player changed:" << m_activePlayer << data.first().toMap().value("type").toString(); - if (data.first().toMap().contains("type")) { - emit activePlayerChanged(data.first().toMap().value("type").toString()); - } else { - // Player map doesn't contain type... sometimes... looks like a kodi bug... Assume 1 is video, 2 is music... - switch (m_activePlayer) { - case 1: - emit activePlayerChanged("video"); - break; - case 2: - emit activePlayerChanged("music"); - break; - case 3: - emit activePlayerChanged("picture"); - break; - } - } + emit activePlayerChanged(data.first().toMap().value("type").toString()); - updatePlayerProperties(); + updateMetadata(); } void Kodi::playerPropertiesReceived(const QVariantMap &properties) @@ -605,6 +590,9 @@ void Kodi::mediaMetaDataReceived(const QVariantMap &data) QVariantMap item = data.value("item").toMap(); QString title = item.value("title").toString(); + if (title.isEmpty()) { // Fall back to label if not title present + title = item.value("label").toString(); + } QString artist; QString collection; if (item.value("type").toString() == "song") { @@ -648,13 +636,15 @@ void Kodi::processNotification(const QString &method, const QVariantMap ¶ms) if (method == "Application.OnVolumeChanged") { QVariantMap data = params.value("data").toMap(); onVolumeChanged(data.value("volume").toInt(), data.value("muted").toBool()); - } else if (method == "Player.OnPlay" || method == "Player.OnResume") { + } else if (method == "Player.OnPlay" || method == "Player.OnResume" || method == "Player.OnAVStart") { onPlaybackStatusChanged("Playing"); - activePlayersChanged(QVariantList() << params.value("data").toMap().value("player")); + update(); } else if (method == "Player.OnPause") { - emit playbackStatusChanged("Paused"); + onPlaybackStatusChanged("Paused"); + update(); } else if (method == "Player.OnStop") { - activePlayersChanged(QVariantList()); + onPlaybackStatusChanged("Stopped"); + update(); } } @@ -681,7 +671,7 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res if (method == "Player.GetActivePlayers") { qCDebug(dcKodi) << "Active players changed" << response; - emit activePlayersChanged(response.value("result").toList()); + activePlayersChanged(response.value("result").toList()); return; } @@ -693,7 +683,7 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res if (method == "Player.GetItem") { qCDebug(dcKodi) << "Played item received" << response; - emit mediaMetaDataReceived(response.value("result").toMap()); + mediaMetaDataReceived(response.value("result").toMap()); return; } From ae883cd0a418475bafe98a8499cbe7b0bf5c22fe Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 19 Oct 2019 03:59:50 +0200 Subject: [PATCH 3/4] fix action reply --- kodi/kodi.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kodi/kodi.cpp b/kodi/kodi.cpp index ba1497c8..b2ffec84 100644 --- a/kodi/kodi.cpp +++ b/kodi/kodi.cpp @@ -953,11 +953,6 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res return; } - if (method == "GUI.ShowNotification" || method == "Input.ExecuteAction") { - emit actionExecuted(id, !response.contains("error")); - return; - } - if (method == "VideoLibrary.Scan" || method == "VideoLibrary.Clean" || method == "AudioLibrary.Scan" || method == "AudioLibrary.Clean") { emit browserItemActionExecuted(id, !response.contains("error")); return; @@ -965,9 +960,11 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res if (method == "Player.Open") { emit browserItemExecuted(id, !response.contains("error")); + return; } - qCWarning(dcKodi()) << "unhandled reply" << method << response; + // Default + emit actionExecuted(id, !response.contains("error")); } void Kodi::updatePlayerProperties() From c2ca4038da1d262e5096ed2a266ac759fbf51633 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 21 Oct 2019 11:32:53 +0200 Subject: [PATCH 4/4] Fix notification handling --- kodi/devicepluginkodi.cpp | 52 ++++++++------------------------------ kodi/devicepluginkodi.h | 4 +-- kodi/kodi.cpp | 53 ++++++++++++++++++++++++++++----------- kodi/kodi.h | 4 +-- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/kodi/devicepluginkodi.cpp b/kodi/devicepluginkodi.cpp index 7899b1db..7a109a7d 100644 --- a/kodi/devicepluginkodi.cpp +++ b/kodi/devicepluginkodi.cpp @@ -72,8 +72,6 @@ void DevicePluginKodi::setupDevice(DeviceSetupInfo *info) connect(kodi, &Kodi::connectionStatusChanged, this, &DevicePluginKodi::onConnectionChanged); connect(kodi, &Kodi::stateChanged, this, &DevicePluginKodi::onStateChanged); connect(kodi, &Kodi::actionExecuted, this, &DevicePluginKodi::onActionExecuted); - connect(kodi, &Kodi::versionDataReceived, this, &DevicePluginKodi::versionDataReceived); - connect(kodi, &Kodi::updateDataReceived, this, &DevicePluginKodi::onSetupFinished); connect(kodi, &Kodi::playbackStatusChanged, this, &DevicePluginKodi::onPlaybackStatusChanged); connect(kodi, &Kodi::browserItemExecuted, this, &DevicePluginKodi::onBrowserItemExecuted); connect(kodi, &Kodi::browserItemActionExecuted, this, &DevicePluginKodi::onBrowserItemActionExecuted); @@ -343,18 +341,24 @@ void DevicePluginKodi::onPluginTimer() } } -void DevicePluginKodi::onConnectionChanged() +void DevicePluginKodi::onConnectionChanged(bool connected) { Kodi *kodi = static_cast(sender()); Device *device = m_kodis.value(kodi); - if (kodi->connected()) { - // if this is the first setup, check version - if (m_asyncSetups.contains(kodi)) { - kodi->checkVersion(); + // Finish setup + DeviceSetupInfo *info = m_asyncSetups.value(kodi); + if (info) { + if (connected) { + info->finish(Device::DeviceErrorNoError); + } else { + //: Error setting up device + m_asyncSetups.take(kodi)->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("This installation of Kodi is too old. Please upgrade your Kodi system.")); } } + kodi->showNotification("nymea", tr("Connected"), 2000, "info"); + device->setStateValue(kodiConnectedStateTypeId, kodi->connected()); } @@ -392,40 +396,6 @@ void DevicePluginKodi::onBrowserItemActionExecuted(int actionId, bool success) m_pendingBrowserItemActions.take(actionId)->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure); } -void DevicePluginKodi::versionDataReceived(const QVariantMap &data) -{ - Kodi *kodi = static_cast(sender()); - - QVariantMap version = data.value("version").toMap(); - QString apiVersion = QString("%1.%2.%3").arg(version.value("major").toString()).arg(version.value("minor").toString()).arg(version.value("patch").toString()); - qCDebug(dcKodi) << "API Version:" << apiVersion; - - if (version.value("major").toInt() < 6) { - qCWarning(dcKodi) << "incompatible api version:" << apiVersion; - if (m_asyncSetups.contains(kodi)) { - //: Error setting up device - m_asyncSetups.take(kodi)->finish(Device::DeviceErrorHardwareFailure, QT_TR_NOOP("This installation of Kodi is too old. Please upgrade your Kodi system.")); - } - return; - } - kodi->update(); -} - -void DevicePluginKodi::onSetupFinished(const QVariantMap &data) -{ - Kodi *kodi = static_cast(sender()); - - QVariantMap version = data.value("version").toMap(); - QString kodiVersion = QString("%1.%2 (%3)").arg(version.value("major").toString()).arg(version.value("minor").toString()).arg(version.value("tag").toString()); - qCDebug(dcKodi) << "Version:" << kodiVersion; - - if (m_asyncSetups.contains(kodi)) { - m_asyncSetups.take(kodi)->finish(Device::DeviceErrorNoError); - } - - kodi->showNotification("nymea", tr("Connected"), 2000, "info"); -} - void DevicePluginKodi::onPlaybackStatusChanged(const QString &playbackStatus) { Kodi *kodi = static_cast(sender()); diff --git a/kodi/devicepluginkodi.h b/kodi/devicepluginkodi.h index f1328ad1..ad3fbb7b 100644 --- a/kodi/devicepluginkodi.h +++ b/kodi/devicepluginkodi.h @@ -63,13 +63,11 @@ private: private slots: void onPluginTimer(); - void onConnectionChanged(); + void onConnectionChanged(bool connected); void onStateChanged(); void onActionExecuted(int actionId, bool success); void onBrowserItemExecuted(int actionId, bool success); void onBrowserItemActionExecuted(int actionId, bool success); - void versionDataReceived(const QVariantMap &data); - void onSetupFinished(const QVariantMap &data); void onPlaybackStatusChanged(const QString &playbackStatus); }; diff --git a/kodi/kodi.cpp b/kodi/kodi.cpp index b2ffec84..cebf9369 100644 --- a/kodi/kodi.cpp +++ b/kodi/kodi.cpp @@ -33,7 +33,7 @@ Kodi::Kodi(const QHostAddress &hostAddress, int port, int httpPort, QObject *par m_volume(-1) { m_connection = new KodiConnection(hostAddress, port, this); - connect (m_connection, &KodiConnection::connectionStatusChanged, this, &Kodi::connectionStatusChanged); + connect (m_connection, &KodiConnection::connectionStatusChanged, this, &Kodi::onConnectionStatusChanged); m_jsonHandler = new KodiJsonHandler(m_connection, this); connect(m_jsonHandler, &KodiJsonHandler::notificationReceived, this, &Kodi::processNotification); @@ -532,6 +532,15 @@ int Kodi::executeBrowserItemAction(const QString &itemId, const ActionTypeId &ac return m_jsonHandler->sendData(scope + "." + method, QVariantMap()); } +void Kodi::onConnectionStatusChanged() +{ + if (m_connection->connected()) { + checkVersion(); + } else { + emit connectionStatusChanged(false); + } +} + void Kodi::onVolumeChanged(const int &volume, const bool &muted) { if (m_volume != volume || m_muted != muted) { @@ -636,14 +645,14 @@ void Kodi::processNotification(const QString &method, const QVariantMap ¶ms) if (method == "Application.OnVolumeChanged") { QVariantMap data = params.value("data").toMap(); onVolumeChanged(data.value("volume").toInt(), data.value("muted").toBool()); - } else if (method == "Player.OnPlay" || method == "Player.OnResume" || method == "Player.OnAVStart") { - onPlaybackStatusChanged("Playing"); - update(); - } else if (method == "Player.OnPause") { - onPlaybackStatusChanged("Paused"); - update(); - } else if (method == "Player.OnStop") { - onPlaybackStatusChanged("Stopped"); + return; + } + + if (method == "Player.OnPlay" || + method == "Player.OnResume" || + method == "Player.OnPause" || + method == "Player.OnStop" || + method == "Player.OnAVChange") { update(); } } @@ -657,27 +666,43 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res qCWarning(dcKodi) << "got error response for request " << method << ":" << response.value("error").toMap().value("message").toString(); } + if (method == "JSONRPC.Version") { + qCDebug(dcKodi) << "got version response" << method; + QVariantMap data = response.value("result").toMap(); + QVariantMap version = data.value("version").toMap(); + QString apiVersion = QString("%1.%2.%3").arg(version.value("major").toString()).arg(version.value("minor").toString()).arg(version.value("patch").toString()); + qCDebug(dcKodi) << "API Version:" << apiVersion; + + if (version.value("major").toInt() < 6) { + qCWarning(dcKodi) << "incompatible api version:" << apiVersion; + m_connection->disconnectKodi(); + emit connectionStatusChanged(false); + return; + } + emit connectionStatusChanged(true); + + update(); + return; + } + if (method == "Application.GetProperties") { //qCDebug(dcKodi) << "got update response" << reply.method(); emit updateDataReceived(response.value("result").toMap()); return; } - if (method == "JSONRPC.Version") { - qCDebug(dcKodi) << "got version response" << method; - emit versionDataReceived(response.value("result").toMap()); - return; - } if (method == "Player.GetActivePlayers") { qCDebug(dcKodi) << "Active players changed" << response; activePlayersChanged(response.value("result").toList()); + updatePlayerProperties(); return; } if (method == "Player.GetProperties") { qCDebug(dcKodi) << "Player properties received" << response; playerPropertiesReceived(response.value("result").toMap()); + updateMetadata(); return; } diff --git a/kodi/kodi.h b/kodi/kodi.h index 50bf2e0e..5ea0069e 100644 --- a/kodi/kodi.h +++ b/kodi/kodi.h @@ -74,20 +74,20 @@ public: int executeBrowserItemAction(const QString &itemId, const ActionTypeId &actionTypeId); signals: - void connectionStatusChanged(); + void connectionStatusChanged(bool connected); void stateChanged(); void activePlayerChanged(const QString &playerType); void actionExecuted(int actionId, bool success); void browserItemExecuted(int actionId, bool success); void browserItemActionExecuted(int actionId, bool success); void updateDataReceived(const QVariantMap &data); - void versionDataReceived(const QVariantMap &data); void playbackStatusChanged(const QString &playbackState); void mediaMetadataChanged(const QString &title, const QString &artist, const QString &collection, const QString &artwork); void shuffleChanged(bool shuffle); void repeatChanged(const QString &repeat); private slots: + void onConnectionStatusChanged(); void onVolumeChanged(const int &volume, const bool &muted); void onUpdateFinished(const QVariantMap &data); void activePlayersChanged(const QVariantList &data);