From 69a3a1835fab03d6cfbdd661772fc3ae412c0ace Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 18 Sep 2019 02:04:02 +0200 Subject: [PATCH] Update Kodi device plugin --- kodi/devicepluginkodi.cpp | 222 ++++++++++++++++++++------------------ kodi/devicepluginkodi.h | 24 +++-- kodi/kodi.cpp | 177 +++++++++++++++--------------- kodi/kodi.h | 17 +-- 4 files changed, 224 insertions(+), 216 deletions(-) diff --git a/kodi/devicepluginkodi.cpp b/kodi/devicepluginkodi.cpp index 9d8f4b3d..7899b1db 100644 --- a/kodi/devicepluginkodi.cpp +++ b/kodi/devicepluginkodi.cpp @@ -60,8 +60,9 @@ void DevicePluginKodi::init() connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginKodi::onPluginTimer); } -Device::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device) +void DevicePluginKodi::setupDevice(DeviceSetupInfo *info) { + Device *device = info->device(); qCDebug(dcKodi) << "Setup Kodi device" << device->paramValue(kodiDeviceIpParamTypeId).toString(); QString ipString = device->paramValue(kodiDeviceIpParamTypeId).toString(); int port = device->paramValue(kodiDevicePortParamTypeId).toInt(); @@ -74,8 +75,7 @@ Device::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device) connect(kodi, &Kodi::versionDataReceived, this, &DevicePluginKodi::versionDataReceived); connect(kodi, &Kodi::updateDataReceived, this, &DevicePluginKodi::onSetupFinished); connect(kodi, &Kodi::playbackStatusChanged, this, &DevicePluginKodi::onPlaybackStatusChanged); - connect(kodi, &Kodi::browseResult, this, &DevicePluginKodi::browseRequestFinished); - connect(kodi, &Kodi::browserItemResult, this, &DevicePluginKodi::browserItemRequestFinished); + connect(kodi, &Kodi::browserItemExecuted, this, &DevicePluginKodi::onBrowserItemExecuted); connect(kodi, &Kodi::browserItemActionExecuted, this, &DevicePluginKodi::onBrowserItemActionExecuted); connect(kodi, &Kodi::activePlayerChanged, device, [device](const QString &playerType){ @@ -133,11 +133,10 @@ Device::DeviceSetupStatus DevicePluginKodi::setupDevice(Device *device) } }); m_kodis.insert(kodi, device); - m_asyncSetups.append(kodi); + m_asyncSetups.insert(kodi, info); + connect(info, &QObject::destroyed, this, [this, kodi](){ m_asyncSetups.remove(kodi); }); kodi->connectKodi(); - - return Device::DeviceSetupStatusAsync; } void DevicePluginKodi::deviceRemoved(Device *device) @@ -148,14 +147,17 @@ void DevicePluginKodi::deviceRemoved(Device *device) kodi->deleteLater(); } -Device::DeviceError DevicePluginKodi::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) +void DevicePluginKodi::discoverDevices(DeviceDiscoveryInfo *info) { - Q_UNUSED(params) - Q_UNUSED(deviceClassId) ZeroConfServiceBrowser *serviceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_xbmc-jsonrpc._tcp"); + connect(info, &QObject::destroyed, serviceBrowser, &QObject::deleteLater); + ZeroConfServiceBrowser *httpServiceBrowser = hardwareManager()->zeroConfController()->createServiceBrowser("_http._tcp"); - QTimer::singleShot(5000, this, [this, serviceBrowser, httpServiceBrowser](){ + connect(info, &QObject::destroyed, httpServiceBrowser, &QObject::deleteLater); + + QTimer::singleShot(5000, info, [this, info, serviceBrowser, httpServiceBrowser](){ + QHash descriptors; foreach (const ZeroConfServiceEntry avahiEntry, serviceBrowser->serviceEntries()) { @@ -213,124 +215,122 @@ Device::DeviceError DevicePluginKodi::discoverDevices(const DeviceClassId &devic foreach (const DeviceDescriptor &d, descriptors.values()) { qCDebug(dcKodi()) << "Returning descritpor:" << d.params(); } - emit devicesDiscovered(kodiDeviceClassId, descriptors.values()); - serviceBrowser->deleteLater(); - httpServiceBrowser->deleteLater(); + info->addDeviceDescriptors(descriptors.values()); + info->finish(Device::DeviceErrorNoError); }); - - return Device::DeviceErrorAsync; } -Device::DeviceError DevicePluginKodi::executeAction(Device *device, const Action &action) +void DevicePluginKodi::executeAction(DeviceActionInfo *info) { - if (device->deviceClassId() == kodiDeviceClassId) { - Kodi *kodi = m_kodis.key(device); + Action action = info->action(); + Device *device = info->device(); + Kodi *kodi = m_kodis.key(device); - // check connection state - if (!kodi->connected()) { - return Device::DeviceErrorHardwareNotAvailable; - } + // check connection state + if (!kodi->connected()) { + return info->finish(Device::DeviceErrorHardwareNotAvailable); + } - int commandId = -1; - if (action.actionTypeId() == kodiNotifyActionTypeId) { - commandId = kodi->showNotification( - action.param(kodiNotifyActionTitleParamTypeId).value().toString(), - action.param(kodiNotifyActionBodyParamTypeId).value().toString(), - 8000, - action.param(kodiNotifyActionTypeParamTypeId).value().toString()); - } else if (action.actionTypeId() == kodiVolumeActionTypeId) { - commandId = kodi->setVolume(action.param(kodiVolumeActionVolumeParamTypeId).value().toInt()); - } else if (action.actionTypeId() == kodiMuteActionTypeId) { - commandId = kodi->setMuted(action.param(kodiMuteActionMuteParamTypeId).value().toBool()); - } else if (action.actionTypeId() == kodiNavigateActionTypeId) { - commandId = kodi->navigate(action.param(kodiNavigateActionToParamTypeId).value().toString()); - } else if (action.actionTypeId() == kodiSystemActionTypeId) { - commandId = kodi->systemCommand(action.param(kodiSystemActionSystemCommandParamTypeId).value().toString()); - } else if(action.actionTypeId() == kodiSkipBackActionTypeId) { - commandId = kodi->navigate("skipprevious"); - } else if(action.actionTypeId() == kodiFastRewindActionTypeId) { - commandId = kodi->navigate("rewind"); - } else if(action.actionTypeId() == kodiStopActionTypeId) { - commandId = kodi->navigate("stop"); - } else if(action.actionTypeId() == kodiPlayActionTypeId) { - commandId = kodi->navigate("play"); - } else if(action.actionTypeId() == kodiPauseActionTypeId) { - commandId = kodi->navigate("pause"); - } else if(action.actionTypeId() == kodiFastForwardActionTypeId) { - commandId = kodi->navigate("fastforward"); - } else if(action.actionTypeId() == kodiSkipNextActionTypeId) { - commandId = kodi->navigate("skipnext"); - } else if (action.actionTypeId() == kodiShuffleActionTypeId) { - commandId = kodi->setShuffle(action.param(kodiShuffleActionShuffleParamTypeId).value().toBool()); - } else if (action.actionTypeId() == kodiRepeatActionTypeId) { - QString repeat = action.param(kodiRepeatActionRepeatParamTypeId).value().toString(); - if (repeat == "One") { - commandId = kodi->setRepeat("one"); - } else if (repeat == "All") { - commandId = kodi->setRepeat("all"); - } else { - commandId = kodi->setRepeat("off"); - } + int commandId = -1; + if (action.actionTypeId() == kodiNotifyActionTypeId) { + commandId = kodi->showNotification( + action.param(kodiNotifyActionTitleParamTypeId).value().toString(), + action.param(kodiNotifyActionBodyParamTypeId).value().toString(), + 8000, + action.param(kodiNotifyActionTypeParamTypeId).value().toString()); + } else if (action.actionTypeId() == kodiVolumeActionTypeId) { + commandId = kodi->setVolume(action.param(kodiVolumeActionVolumeParamTypeId).value().toInt()); + } else if (action.actionTypeId() == kodiMuteActionTypeId) { + commandId = kodi->setMuted(action.param(kodiMuteActionMuteParamTypeId).value().toBool()); + } else if (action.actionTypeId() == kodiNavigateActionTypeId) { + commandId = kodi->navigate(action.param(kodiNavigateActionToParamTypeId).value().toString()); + } else if (action.actionTypeId() == kodiSystemActionTypeId) { + commandId = kodi->systemCommand(action.param(kodiSystemActionSystemCommandParamTypeId).value().toString()); + } else if(action.actionTypeId() == kodiSkipBackActionTypeId) { + commandId = kodi->navigate("skipprevious"); + } else if(action.actionTypeId() == kodiFastRewindActionTypeId) { + commandId = kodi->navigate("rewind"); + } else if(action.actionTypeId() == kodiStopActionTypeId) { + commandId = kodi->navigate("stop"); + } else if(action.actionTypeId() == kodiPlayActionTypeId) { + commandId = kodi->navigate("play"); + } else if(action.actionTypeId() == kodiPauseActionTypeId) { + commandId = kodi->navigate("pause"); + } else if(action.actionTypeId() == kodiFastForwardActionTypeId) { + commandId = kodi->navigate("fastforward"); + } else if(action.actionTypeId() == kodiSkipNextActionTypeId) { + commandId = kodi->navigate("skipnext"); + } else if (action.actionTypeId() == kodiShuffleActionTypeId) { + commandId = kodi->setShuffle(action.param(kodiShuffleActionShuffleParamTypeId).value().toBool()); + } else if (action.actionTypeId() == kodiRepeatActionTypeId) { + QString repeat = action.param(kodiRepeatActionRepeatParamTypeId).value().toString(); + if (repeat == "One") { + commandId = kodi->setRepeat("one"); + } else if (repeat == "All") { + commandId = kodi->setRepeat("all"); } else { - qWarning(dcKodi()) << "Unhandled action type" << action.actionTypeId(); - return Device::DeviceErrorActionTypeNotFound; + commandId = kodi->setRepeat("off"); } - m_pendingActions.insert(commandId, action.id()); - return Device::DeviceErrorAsync; + } else { + qWarning(dcKodi()) << "Unhandled action type" << action.actionTypeId(); + return info->finish(Device::DeviceErrorActionTypeNotFound); } - return Device::DeviceErrorDeviceClassNotFound; + + m_pendingActions.insert(commandId, info); + connect(info, &QObject::destroyed, this, [this, commandId](){ m_pendingActions.remove(commandId); }); } -Device::BrowseResult DevicePluginKodi::browseDevice(Device *device, Device::BrowseResult result, const QString &itemId, const QLocale &locale) +void DevicePluginKodi::browseDevice(BrowseResult *result) { - Q_UNUSED(locale) - - Kodi *kodi = m_kodis.key(device); + Kodi *kodi = m_kodis.key(result->device()); if (!kodi) { - result.status = Device::DeviceErrorHardwareNotAvailable; - return result; + result->finish(Device::DeviceErrorHardwareNotAvailable); + return; } - return kodi->browse(itemId, result); + kodi->browse(result); } -Device::BrowserItemResult DevicePluginKodi::browserItem(Device *device, Device::BrowserItemResult result, const QString &itemId, const QLocale &locale) +void DevicePluginKodi::browserItem(BrowserItemResult *result) { - Q_UNUSED(locale) - - Kodi *kodi = m_kodis.key(device); + Kodi *kodi = m_kodis.key(result->device()); if (!kodi) { - result.status = Device::DeviceErrorHardwareNotAvailable; - return result; + result->finish(Device::DeviceErrorHardwareNotAvailable); + return; } - return kodi->browserItem(itemId, result); - + kodi->browserItem(result); } -Device::DeviceError DevicePluginKodi::executeBrowserItem(Device *device, const BrowserAction &browserAction) +void DevicePluginKodi::executeBrowserItem(BrowserActionInfo *info) { - Kodi *kodi = m_kodis.key(device); + Kodi *kodi = m_kodis.key(info->device()); if (!kodi) { - return Device::DeviceErrorHardwareNotAvailable; + info->finish(Device::DeviceErrorHardwareNotAvailable); + return; } - return kodi->launchBrowserItem(browserAction.itemId()); -} - -Device::DeviceError DevicePluginKodi::executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction) -{ - Kodi *kodi = m_kodis.key(device); - if (!kodi) { - return Device::DeviceErrorHardwareNotAvailable; - } - - int id = kodi->executeBrowserItemAction(browserItemAction.itemId(), browserItemAction.actionTypeId()); + int id = kodi->launchBrowserItem(info->browserAction().itemId()); if (id == -1) { - return Device::DeviceErrorHardwareFailure; + return info->finish(Device::DeviceErrorHardwareFailure); } - m_pendingBrowserItemActions.insert(id, browserItemAction.id()); - return Device::DeviceErrorAsync; + m_pendingBrowserActions.insert(id, info); + connect(info, &QObject::destroyed, this, [this, id](){ m_pendingBrowserActions.remove(id); }); +} + +void DevicePluginKodi::executeBrowserItemAction(BrowserItemActionInfo *info) +{ + Kodi *kodi = m_kodis.key(info->device()); + if (!kodi) { + return info->finish(Device::DeviceErrorHardwareNotAvailable); + } + + int id = kodi->executeBrowserItemAction(info->browserItemAction().itemId(), info->browserItemAction().actionTypeId()); + if (id == -1) { + return info->finish(Device::DeviceErrorHardwareFailure); + } + m_pendingBrowserItemActions.insert(id, info); + connect(info, &QObject::destroyed, this, [this, id](){ m_pendingBrowserItemActions.remove(id); }); } void DevicePluginKodi::onPluginTimer() @@ -351,7 +351,6 @@ void DevicePluginKodi::onConnectionChanged() if (kodi->connected()) { // if this is the first setup, check version if (m_asyncSetups.contains(kodi)) { - m_asyncSetups.removeAll(kodi); kodi->checkVersion(); } } @@ -374,7 +373,15 @@ void DevicePluginKodi::onActionExecuted(int actionId, bool success) if (!m_pendingActions.contains(actionId)) { return; } - emit actionExecutionFinished(m_pendingActions.take(actionId), success ? Device::DeviceErrorNoError : Device::DeviceErrorInvalidParameter); + m_pendingActions.take(actionId)->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorInvalidParameter); +} + +void DevicePluginKodi::onBrowserItemExecuted(int actionId, bool success) +{ + if (!m_pendingBrowserActions.contains(actionId)) { + return; + } + m_pendingBrowserActions.take(actionId)->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorInvalidParameter); } void DevicePluginKodi::onBrowserItemActionExecuted(int actionId, bool success) @@ -382,13 +389,12 @@ void DevicePluginKodi::onBrowserItemActionExecuted(int actionId, bool success) if (!m_pendingBrowserItemActions.contains(actionId)) { return; } - emit browserItemActionExecutionFinished(m_pendingBrowserItemActions.take(actionId), success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure); + m_pendingBrowserItemActions.take(actionId)->finish(success ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareFailure); } void DevicePluginKodi::versionDataReceived(const QVariantMap &data) { Kodi *kodi = static_cast(sender()); - Device *device = m_kodis.value(kodi); 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()); @@ -396,7 +402,10 @@ void DevicePluginKodi::versionDataReceived(const QVariantMap &data) if (version.value("major").toInt() < 6) { qCWarning(dcKodi) << "incompatible api version:" << apiVersion; - emit deviceSetupFinished(device, Device::DeviceSetupStatusFailure); + 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(); @@ -405,13 +414,14 @@ void DevicePluginKodi::versionDataReceived(const QVariantMap &data) void DevicePluginKodi::onSetupFinished(const QVariantMap &data) { Kodi *kodi = static_cast(sender()); - Device *device = m_kodis.value(kodi); 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; - emit deviceSetupFinished(device, Device::DeviceSetupStatusSuccess); + if (m_asyncSetups.contains(kodi)) { + m_asyncSetups.take(kodi)->finish(Device::DeviceErrorNoError); + } kodi->showNotification("nymea", tr("Connected"), 2000, "info"); } diff --git a/kodi/devicepluginkodi.h b/kodi/devicepluginkodi.h index 5aa3fb50..f1328ad1 100644 --- a/kodi/devicepluginkodi.h +++ b/kodi/devicepluginkodi.h @@ -42,29 +42,31 @@ public: ~DevicePluginKodi(); void init() override; - Device::DeviceSetupStatus setupDevice(Device *device) override; + void setupDevice(DeviceSetupInfo *info) override; void deviceRemoved(Device *device) override; - Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; - Device::DeviceError executeAction(Device *device, const Action &action) override; + void discoverDevices(DeviceDiscoveryInfo *info) override; + void executeAction(DeviceActionInfo *info) override; - Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &itemId, const QLocale &locale) override; - Device::BrowserItemResult browserItem(Device *device, Device::BrowserItemResult result, const QString &itemId, const QLocale &locale) override; - Device::DeviceError executeBrowserItem(Device *device, const BrowserAction &browserAction) override; - Device::DeviceError executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction) override; + void browseDevice(BrowseResult *result) override; + void browserItem(BrowserItemResult *result) override; + void executeBrowserItem(BrowserActionInfo *info) override; + void executeBrowserItemAction(BrowserItemActionInfo *info) override; private: PluginTimer *m_pluginTimer; - QHash m_kodis; - QList m_asyncSetups; + QHash m_kodis; + QHash m_asyncSetups; - QHash m_pendingActions; - QHash m_pendingBrowserItemActions; + QHash m_pendingActions; + QHash m_pendingBrowserActions; + QHash m_pendingBrowserItemActions; private slots: void onPluginTimer(); void onConnectionChanged(); 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); diff --git a/kodi/kodi.cpp b/kodi/kodi.cpp index 03a2a0c8..267549e6 100644 --- a/kodi/kodi.cpp +++ b/kodi/kodi.cpp @@ -301,24 +301,24 @@ void Kodi::disconnectKodi() m_connection->disconnectKodi(); } -Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &result) +void Kodi::browse(BrowseResult *result) { // m_jsonHandler->sendData() - VirtualFsNode *node = m_virtualFs->findNode(itemId); + VirtualFsNode *node = m_virtualFs->findNode(result->itemId()); if (node) { if (node->getMethod.isEmpty()) { foreach (VirtualFsNode *child, node->childs) { - result.items.append(child->item); + result->addItem(child->item); } - return result; + result->finish(Device::DeviceErrorNoError); + return; } qCDebug(dcKodi()) << "Sending:" << node->getMethod << node->getParams; int id = m_jsonHandler->sendData(node->getMethod, node->getParams); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } QVariantMap sort; @@ -327,8 +327,8 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r QVariantList properties; properties.append("thumbnail"); - if (itemId.startsWith("artist:")) { - QString idString = itemId; + if (result->itemId().startsWith("artist:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^artist:")); QVariantMap filter; filter.insert("artistid", idString.toInt()); @@ -340,12 +340,11 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r params.insert("properties", albumProperties); int id = m_jsonHandler->sendData("AudioLibrary.GetAlbums", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - if (itemId.startsWith("album:")) { - QString idString = itemId; + if (result->itemId().startsWith("album:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^album:")); QVariantMap filter; filter.insert("albumid", idString.toInt()); @@ -359,12 +358,11 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r params.insert("properties", songProperties); int id = m_jsonHandler->sendData("AudioLibrary.GetSongs", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - if (itemId.startsWith("tvshow:")) { - QString idString = itemId; + if (result->itemId().startsWith("tvshow:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^tvshow:")); QVariantMap params; params.insert("tvshowid", idString.toInt()); @@ -376,12 +374,11 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r params.insert("properties", properties); int id = m_jsonHandler->sendData("VideoLibrary.GetSeasons", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - if (itemId.startsWith("season:")) { - QString idString = itemId; + if (result->itemId().startsWith("season:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^season:")); int seasonId = idString.left(idString.indexOf(",")).toInt(); idString.remove(QRegExp("^[0-9]*,tvshow:")); @@ -397,12 +394,11 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r qCDebug(dcKodi()) << "getting episodes:" << params; int id = m_jsonHandler->sendData("VideoLibrary.GetEpisodes", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - if (itemId.startsWith("addon:")) { - QString idString = itemId; + if (result->itemId().startsWith("addon:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^addon:")); QVariantMap params; params.insert("directory", "plugin://" + idString); @@ -413,12 +409,11 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r qCDebug(dcKodi()) << "Sending" << params; int id = m_jsonHandler->sendData("Files.GetDirectory", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - if (itemId.startsWith("file:")) { - QString idString = itemId; + if (result->itemId().startsWith("file:")) { + QString idString = result->itemId(); idString.remove(QRegExp("^file:")); QVariantMap params; params.insert("directory", idString); @@ -426,16 +421,15 @@ Device::BrowseResult Kodi::browse(const QString &itemId, Device::BrowseResult &r qCDebug(dcKodi()) << "Sending" << params; int id = m_jsonHandler->sendData("Files.GetDirectory", params); m_pendingBrowseRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; + return; } - result.status = Device::DeviceErrorItemNotFound; - return result; + result->finish(Device::DeviceErrorItemNotFound); } -Device::BrowserItemResult Kodi::browserItem(const QString &itemId, Device::BrowserItemResult &result) +void Kodi::browserItem(BrowserItemResult *result) { + QString itemId = result->itemId(); qCDebug(dcKodi()) << "Getting details for" << itemId; QString idString = itemId; QString method; @@ -458,16 +452,14 @@ Device::BrowserItemResult Kodi::browserItem(const QString &itemId, Device::Brows method = "VideoLibrary.GetMusicVideoDetails"; } else { qCWarning(dcKodi()) << "Unhandled browserItem request!" << itemId; - result.status = Device::DeviceErrorUnsupportedFeature; - return result; + result->finish(Device::DeviceErrorItemNotFound); + return; } int id = m_jsonHandler->sendData(method, params); m_pendingBrowserItemRequests.insert(id, result); - result.status = Device::DeviceErrorAsync; - return result; } -Device::DeviceError Kodi::launchBrowserItem(const QString &itemId) +int Kodi::launchBrowserItem(const QString &itemId) { qCDebug(dcKodi()) << "Launching" << itemId; QVariantMap playlistItem; @@ -507,15 +499,14 @@ Device::DeviceError Kodi::launchBrowserItem(const QString &itemId) playlistItem.insert("file", idString); } else { qCWarning(dcKodi()) << "Unhandled launchBrowserItem request!" << itemId; - return Device::DeviceErrorItemNotFound; + return -1; } QVariantMap params; params.clear(); params.insert("item", playlistItem); qCDebug(dcKodi()) << "Player.Open" << params; - m_jsonHandler->sendData("Player.Open", params); - return Device::DeviceErrorNoError; + return m_jsonHandler->sendData("Player.Open", params); } int Kodi::executeBrowserItemAction(const QString &itemId, const ActionTypeId &actionTypeId) @@ -699,7 +690,7 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res } if (method == "AudioLibrary.GetArtists") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &artistVariant, response.value("result").toMap().value("artists").toList()) { QVariantMap artist = artistVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << artist; @@ -716,14 +707,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res } item.setDescription(description.join(" - ")); qCDebug(dcKodi()) << "Thumbnail" << item.thumbnail(); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "AudioLibrary.GetAlbums") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &albumVariant, response.value("result").toMap().value("albums").toList()) { QVariantMap album = albumVariant.toMap(); BrowserItem item("album:" + album.value("albumid").toString(), album.value("label").toString()); @@ -738,14 +729,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res description.append(album.value("year").toString()); } item.setDescription(description.join(" - ")); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "AudioLibrary.GetSongs") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); int i = 0; foreach (const QVariant &songVariant, response.value("result").toMap().value("songs").toList()) { QVariantMap song = songVariant.toMap(); @@ -771,16 +762,16 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res description.append(song.value("year").toString()); } item.setDescription(description.join(" - ")); - result.items.append(item); + result->addItem(item); i++; } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "VideoLibrary.GetMovies") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &movieVariant, response.value("result").toMap().value("movies").toList()) { QVariantMap movie = movieVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << movie; @@ -803,14 +794,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res QString duration; duration = QString("%1:%2").arg(hours).arg(minutes, 2, 10, QChar('0')); item.setDescription(movie.value("year").toString() + " - " + duration + " - " + rating); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "VideoLibrary.GetTVShows") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &tvShowVariant, response.value("result").toMap().value("tvshows").toList()) { QVariantMap tvShow = tvShowVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << tvShow; @@ -827,14 +818,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res } } item.setDescription(tvShow.value("year").toString() + " - " + tr("%1 seasons").arg(tvShow.value("season").toInt()) + " - " + rating); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "VideoLibrary.GetSeasons") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &seasonVariant, response.value("result").toMap().value("seasons").toList()) { QVariantMap season = seasonVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << season; @@ -843,14 +834,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res item.setIcon(BrowserItem::BrowserIconFolder); item.setThumbnail(prepareThumbnail(season.value("thumbnail").toString())); item.setDescription(season.value("showtitle").toString()); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "VideoLibrary.GetEpisodes") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &episodeVariant, response.value("result").toMap().value("episodes").toList()) { QVariantMap episode = episodeVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << episode; @@ -863,14 +854,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res } else { item.setDescription(episode.value("showtitle").toString()); } - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "VideoLibrary.GetMusicVideos") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &musicVideoVariant, response.value("result").toMap().value("musicvideos").toList()) { QVariantMap musicVideo = musicVideoVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << musicVideo; @@ -878,14 +869,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res item.setExecutable(true); item.setIcon(BrowserItem::BrowserIconVideo); item.setThumbnail(prepareThumbnail(musicVideo.value("thumbnail").toString())); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "Addons.GetAddons") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &addonVariant, response.value("result").toMap().value("addons").toList()) { QVariantMap addon = addonVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << addon; @@ -893,14 +884,14 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res item.setBrowsable(true); item.setIcon(BrowserItem::BrowserIconApplication); item.setThumbnail(prepareThumbnail(addon.value("thumbnail").toString())); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "Files.GetDirectory") { - Device::BrowseResult result = m_pendingBrowseRequests.take(id); + BrowseResult *result = m_pendingBrowseRequests.take(id); foreach (const QVariant &fileVariant, response.value("result").toMap().value("files").toList()) { QVariantMap file = fileVariant.toMap(); qCDebug(dcKodi()) << "Entry:" << file; @@ -916,45 +907,45 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res item.setIcon(BrowserItem::BrowserIconMusic); } item.setThumbnail(prepareThumbnail(file.value("thumbnail").toString())); - result.items.append(item); + result->addItem(item); } - emit browseResult(result); + result->finish(Device::DeviceErrorNoError); return; } if (method == "AudioLibrary.GetSongDetails") { - Device::BrowserItemResult result = m_pendingBrowserItemRequests.take(id); - result.item.setId("song:" + response.value("result").toMap().value("songdetails").toMap().value("songid").toString()); - result.item.setDisplayName(response.value("result").toMap().value("songdetails").toMap().value("label").toString()); - qCDebug(dcKodi()) << "Song details:" << result.item.displayName(); - emit browserItemResult(result); + BrowserItemResult *result = m_pendingBrowserItemRequests.take(id); + BrowserItem item("song:" + response.value("result").toMap().value("songdetails").toMap().value("songid").toString()); + item.setDisplayName(response.value("result").toMap().value("songdetails").toMap().value("label").toString()); + qCDebug(dcKodi()) << "Song details:" << item.displayName(); + result->finish(item); return; } if (method == "VideoLibrary.GetMovieDetails") { - Device::BrowserItemResult result = m_pendingBrowserItemRequests.take(id); - result.item.setId("movie:" + response.value("result").toMap().value("moviedetails").toMap().value("movieid").toString()); - result.item.setDisplayName(response.value("result").toMap().value("moviedetails").toMap().value("label").toString()); - qCDebug(dcKodi()) << "Movie details:" << result.item.displayName(); - emit browserItemResult(result); + BrowserItemResult *result = m_pendingBrowserItemRequests.take(id); + BrowserItem item("movie:" + response.value("result").toMap().value("moviedetails").toMap().value("movieid").toString()); + item.setDisplayName(response.value("result").toMap().value("moviedetails").toMap().value("label").toString()); + qCDebug(dcKodi()) << "Movie details:" << item.displayName(); + result->finish(item); return; } if (method == "VideoLibrary.GetEpisodeDetails") { - Device::BrowserItemResult result = m_pendingBrowserItemRequests.take(id); - result.item.setId("movie:" + response.value("result").toMap().value("episodedetails").toMap().value("episodeid").toString()); - result.item.setDisplayName(response.value("result").toMap().value("episodedetails").toMap().value("label").toString()); - qCDebug(dcKodi()) << "Episode details:" << result.item.displayName(); - emit browserItemResult(result); + BrowserItemResult *result = m_pendingBrowserItemRequests.take(id); + BrowserItem item("movie:" + response.value("result").toMap().value("episodedetails").toMap().value("episodeid").toString()); + item.setDisplayName(response.value("result").toMap().value("episodedetails").toMap().value("label").toString()); + qCDebug(dcKodi()) << "Episode details:" << item.displayName(); + result->finish(item); return; } if (method == "VideoLibrary.GetMusicVideoDetails") { - Device::BrowserItemResult result = m_pendingBrowserItemRequests.take(id); - result.item.setId("movie:" + response.value("result").toMap().value("musicvideodetails").toMap().value("musicvideoid").toString()); - result.item.setDisplayName(response.value("result").toMap().value("musicvideodetails").toMap().value("label").toString()); - qCDebug(dcKodi()) << "Episode details:" << result.item.displayName(); - emit browserItemResult(result); + BrowserItemResult *result = m_pendingBrowserItemRequests.take(id); + BrowserItem item("movie:" + response.value("result").toMap().value("musicvideodetails").toMap().value("musicvideoid").toString()); + item.setDisplayName(response.value("result").toMap().value("musicvideodetails").toMap().value("label").toString()); + qCDebug(dcKodi()) << "Episode details:" << item.displayName(); + result->finish(item); return; } @@ -968,6 +959,10 @@ void Kodi::processResponse(int id, const QString &method, const QVariantMap &res return; } + if (method == "Player.Open") { + emit browserItemExecuted(id, !response.contains("error")); + } + qCWarning(dcKodi()) << "unhandled reply" << method << response; } diff --git a/kodi/kodi.h b/kodi/kodi.h index 7de08831..50bf2e0e 100644 --- a/kodi/kodi.h +++ b/kodi/kodi.h @@ -32,6 +32,8 @@ #include "types/browseritem.h" #include "types/browseritemaction.h" #include "devices/device.h" +#include "devices/browseresult.h" +#include "devices/browseritemresult.h" class Kodi : public QObject { @@ -66,9 +68,9 @@ public: void connectKodi(); void disconnectKodi(); - Device::BrowseResult browse(const QString &itemId, Device::BrowseResult &result); - Device::BrowserItemResult browserItem(const QString &itemId, Device::BrowserItemResult &result); - Device::DeviceError launchBrowserItem(const QString &itemId); + void browse(BrowseResult *result); + void browserItem(BrowserItemResult *result); + int launchBrowserItem(const QString &itemId); int executeBrowserItemAction(const QString &itemId, const ActionTypeId &actionTypeId); signals: @@ -76,15 +78,14 @@ signals: 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); - void browseResult(const Device::BrowseResult &result); - void browserItemResult(const Device::BrowserItemResult &result); - void browserItemActionExecuted(int actionId, bool success); private slots: void onVolumeChanged(const int &volume, const bool &muted); @@ -131,8 +132,8 @@ private: }; VirtualFsNode* m_virtualFs = nullptr; - QHash m_pendingBrowseRequests; - QHash m_pendingBrowserItemRequests; + QHash m_pendingBrowseRequests; + QHash m_pendingBrowserItemRequests; };