summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/interfaces
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 18:07:22 +0000
commitc04dcc2e7d834218ef2d4194331e383402495ae1 (patch)
tree7333e38d10d75386e60f336b80c2443c1166031d /xbmc/addons/interfaces
parentInitial commit. (diff)
downloadkodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz
kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/addons/interfaces')
-rw-r--r--xbmc/addons/interfaces/AddonBase.cpp661
-rw-r--r--xbmc/addons/interfaces/AddonBase.h87
-rw-r--r--xbmc/addons/interfaces/AudioEngine.cpp761
-rw-r--r--xbmc/addons/interfaces/AudioEngine.h212
-rw-r--r--xbmc/addons/interfaces/CMakeLists.txt18
-rw-r--r--xbmc/addons/interfaces/Filesystem.cpp1181
-rw-r--r--xbmc/addons/interfaces/Filesystem.h131
-rw-r--r--xbmc/addons/interfaces/General.cpp468
-rw-r--r--xbmc/addons/interfaces/General.h76
-rw-r--r--xbmc/addons/interfaces/Network.cpp181
-rw-r--r--xbmc/addons/interfaces/Network.h54
-rw-r--r--xbmc/addons/interfaces/gui/CMakeLists.txt11
-rw-r--r--xbmc/addons/interfaces/gui/GUITranslator.cpp969
-rw-r--r--xbmc/addons/interfaces/gui/GUITranslator.h41
-rw-r--r--xbmc/addons/interfaces/gui/General.cpp252
-rw-r--r--xbmc/addons/interfaces/gui/General.h62
-rw-r--r--xbmc/addons/interfaces/gui/ListItem.cpp428
-rw-r--r--xbmc/addons/interfaces/gui/ListItem.h76
-rw-r--r--xbmc/addons/interfaces/gui/Window.cpp1499
-rw-r--r--xbmc/addons/interfaces/gui/Window.h278
-rw-r--r--xbmc/addons/interfaces/gui/controls/Button.cpp146
-rw-r--r--xbmc/addons/interfaces/gui/controls/Button.h56
-rw-r--r--xbmc/addons/interfaces/gui/controls/CMakeLists.txt27
-rw-r--r--xbmc/addons/interfaces/gui/controls/Edit.cpp239
-rw-r--r--xbmc/addons/interfaces/gui/controls/Edit.h67
-rw-r--r--xbmc/addons/interfaces/gui/controls/FadeLabel.cpp130
-rw-r--r--xbmc/addons/interfaces/gui/controls/FadeLabel.h57
-rw-r--r--xbmc/addons/interfaces/gui/controls/Image.cpp92
-rw-r--r--xbmc/addons/interfaces/gui/controls/Image.h57
-rw-r--r--xbmc/addons/interfaces/gui/controls/Label.cpp92
-rw-r--r--xbmc/addons/interfaces/gui/controls/Label.h53
-rw-r--r--xbmc/addons/interfaces/gui/controls/Progress.cpp88
-rw-r--r--xbmc/addons/interfaces/gui/controls/Progress.h53
-rw-r--r--xbmc/addons/interfaces/gui/controls/RadioButton.cpp146
-rw-r--r--xbmc/addons/interfaces/gui/controls/RadioButton.h57
-rw-r--r--xbmc/addons/interfaces/gui/controls/Rendering.cpp148
-rw-r--r--xbmc/addons/interfaces/gui/controls/Rendering.h89
-rw-r--r--xbmc/addons/interfaces/gui/controls/SettingsSlider.cpp311
-rw-r--r--xbmc/addons/interfaces/gui/controls/SettingsSlider.h77
-rw-r--r--xbmc/addons/interfaces/gui/controls/Slider.cpp305
-rw-r--r--xbmc/addons/interfaces/gui/controls/Slider.h78
-rw-r--r--xbmc/addons/interfaces/gui/controls/Spin.cpp346
-rw-r--r--xbmc/addons/interfaces/gui/controls/Spin.h86
-rw-r--r--xbmc/addons/interfaces/gui/controls/TextBox.cpp147
-rw-r--r--xbmc/addons/interfaces/gui/controls/TextBox.h57
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/CMakeLists.txt23
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/ContextMenu.cpp67
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/ContextMenu.h53
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.cpp305
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.h63
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/FileBrowser.cpp403
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/FileBrowser.h116
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Keyboard.cpp319
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Keyboard.h94
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Numeric.cpp270
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Numeric.h74
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/OK.cpp73
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/OK.h57
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Progress.cpp328
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Progress.h65
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Select.cpp143
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/Select.h62
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/TextViewer.cpp64
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/TextViewer.h50
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/YesNo.cpp136
-rw-r--r--xbmc/addons/interfaces/gui/dialogs/YesNo.h72
-rw-r--r--xbmc/addons/interfaces/platform/android/System.cpp57
-rw-r--r--xbmc/addons/interfaces/platform/android/System.h26
68 files changed, 13370 insertions, 0 deletions
diff --git a/xbmc/addons/interfaces/AddonBase.cpp b/xbmc/addons/interfaces/AddonBase.cpp
new file mode 100644
index 0000000..496ca92
--- /dev/null
+++ b/xbmc/addons/interfaces/AddonBase.cpp
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2005-2020 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "AddonBase.h"
+
+#include "GUIUserMessages.h"
+#include "addons/AddonManager.h"
+#include "addons/addoninfo/AddonInfo.h"
+#include "addons/addoninfo/AddonType.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/gui/GUIDialogAddonSettings.h"
+#include "addons/settings/AddonSettings.h"
+#include "application/Application.h"
+#include "filesystem/Directory.h"
+#include "filesystem/SpecialProtocol.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "settings/lib/Setting.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/log.h"
+
+// "C" interface addon callback handle classes
+#include "AudioEngine.h"
+#include "Filesystem.h"
+#include "General.h"
+#include "Network.h"
+#include "gui/General.h"
+
+namespace ADDON
+{
+
+std::vector<ADDON_GET_INTERFACE_FN> Interface_Base::s_registeredInterfaces;
+
+bool Interface_Base::InitInterface(CAddonDll* addon,
+ AddonGlobalInterface& addonInterface,
+ KODI_ADDON_INSTANCE_STRUCT* firstKodiInstance)
+{
+ addonInterface = {};
+
+ addonInterface.addonBase = nullptr;
+ addonInterface.globalSingleInstance = nullptr;
+ addonInterface.firstKodiInstance = firstKodiInstance;
+
+ // Create function list from kodi to addon, generated with malloc to have
+ // compatible with other versions
+ addonInterface.toKodi = new AddonToKodiFuncTable_Addon();
+ addonInterface.toKodi->kodiBase = addon;
+ addonInterface.toKodi->addon_log_msg = addon_log_msg;
+ addonInterface.toKodi->free_string = free_string;
+ addonInterface.toKodi->free_string_array = free_string_array;
+
+ addonInterface.toKodi->kodi_addon = new AddonToKodiFuncTable_kodi_addon();
+ addonInterface.toKodi->kodi_addon->get_addon_path = get_addon_path;
+ addonInterface.toKodi->kodi_addon->get_lib_path = get_lib_path;
+ addonInterface.toKodi->kodi_addon->get_user_path = get_user_path;
+ addonInterface.toKodi->kodi_addon->get_temp_path = get_temp_path;
+ addonInterface.toKodi->kodi_addon->get_localized_string = get_localized_string;
+ addonInterface.toKodi->kodi_addon->open_settings_dialog = open_settings_dialog;
+ addonInterface.toKodi->kodi_addon->is_setting_using_default = is_setting_using_default;
+ addonInterface.toKodi->kodi_addon->get_setting_bool = get_setting_bool;
+ addonInterface.toKodi->kodi_addon->get_setting_int = get_setting_int;
+ addonInterface.toKodi->kodi_addon->get_setting_float = get_setting_float;
+ addonInterface.toKodi->kodi_addon->get_setting_string = get_setting_string;
+ addonInterface.toKodi->kodi_addon->set_setting_bool = set_setting_bool;
+ addonInterface.toKodi->kodi_addon->set_setting_int = set_setting_int;
+ addonInterface.toKodi->kodi_addon->set_setting_float = set_setting_float;
+ addonInterface.toKodi->kodi_addon->set_setting_string = set_setting_string;
+ addonInterface.toKodi->kodi_addon->get_addon_info = get_addon_info;
+ addonInterface.toKodi->kodi_addon->get_type_version = get_type_version;
+ addonInterface.toKodi->kodi_addon->get_interface = get_interface;
+
+ // Related parts becomes set from addon headers, make here to nullptr to allow
+ // checks for right set of them
+ addonInterface.toAddon = new KodiToAddonFuncTable_Addon();
+
+ // Init the other interfaces
+ Interface_General::Init(&addonInterface);
+ Interface_AudioEngine::Init(&addonInterface);
+ Interface_Filesystem::Init(&addonInterface);
+ Interface_Network::Init(&addonInterface);
+ Interface_GUIGeneral::Init(&addonInterface);
+
+ return true;
+}
+
+void Interface_Base::DeInitInterface(AddonGlobalInterface& addonInterface)
+{
+ Interface_GUIGeneral::DeInit(&addonInterface);
+ Interface_Network::DeInit(&addonInterface);
+ Interface_Filesystem::DeInit(&addonInterface);
+ Interface_AudioEngine::DeInit(&addonInterface);
+ Interface_General::DeInit(&addonInterface);
+
+ if (addonInterface.toKodi)
+ delete addonInterface.toKodi->kodi_addon;
+ delete addonInterface.toKodi;
+ delete addonInterface.toAddon;
+ addonInterface = {};
+}
+
+void Interface_Base::RegisterInterface(ADDON_GET_INTERFACE_FN fn)
+{
+ s_registeredInterfaces.push_back(fn);
+}
+
+bool Interface_Base::UpdateSettingInActiveDialog(CAddonDll* addon,
+ AddonInstanceId instanceId,
+ const char* id,
+ const std::string& value)
+{
+ if (!CServiceBroker::GetGUI()->GetWindowManager().IsWindowActive(WINDOW_DIALOG_ADDON_SETTINGS))
+ return false;
+
+ CGUIDialogAddonSettings* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogAddonSettings>(
+ WINDOW_DIALOG_ADDON_SETTINGS);
+ if (dialog->GetCurrentAddonID() != addon->ID())
+ return false;
+
+ CGUIMessage message(GUI_MSG_SETTING_UPDATED, 0, 0);
+ std::vector<std::string> params;
+ params.emplace_back(id);
+ params.push_back(value);
+ message.SetStringParams(params);
+ message.SetParam1(instanceId);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(message,
+ WINDOW_DIALOG_ADDON_SETTINGS);
+
+ return true;
+}
+
+/*!
+ * @brief Addon to Kodi basic callbacks below
+ *
+ * The amount of functions here are hold so minimal as possible. Only parts
+ * where needed on nearly every add-on (e.g. addon_log_msg) are to add there.
+ *
+ * More specific parts like e.g. to open files should be added to a separate
+ * part.
+ */
+//@{
+
+void Interface_Base::addon_log_msg(const KODI_ADDON_BACKEND_HDL hdl,
+ const int addonLogLevel,
+ const char* strMessage)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "addon_log_msg(...) called with empty kodi instance pointer");
+ return;
+ }
+
+ int logLevel = LOGNONE;
+ switch (addonLogLevel)
+ {
+ case ADDON_LOG_DEBUG:
+ logLevel = LOGDEBUG;
+ break;
+ case ADDON_LOG_INFO:
+ logLevel = LOGINFO;
+ break;
+ case ADDON_LOG_WARNING:
+ logLevel = LOGWARNING;
+ break;
+ case ADDON_LOG_ERROR:
+ logLevel = LOGERROR;
+ break;
+ case ADDON_LOG_FATAL:
+ logLevel = LOGFATAL;
+ break;
+ default:
+ logLevel = LOGDEBUG;
+ break;
+ }
+
+ CLog::Log(logLevel, "AddOnLog: {}: {}", addon->ID(), strMessage);
+}
+
+char* Interface_Base::get_type_version(const KODI_ADDON_BACKEND_HDL hdl, int type)
+{
+ return strdup(kodi::addon::GetTypeVersion(type));
+}
+
+char* Interface_Base::get_addon_path(const KODI_ADDON_BACKEND_HDL hdl)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "get_addon_path(...) called with empty kodi instance pointer");
+ return nullptr;
+ }
+
+ return strdup(CSpecialProtocol::TranslatePath(addon->Path()).c_str());
+}
+
+char* Interface_Base::get_lib_path(const KODI_ADDON_BACKEND_HDL hdl)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "get_lib_path(...) called with empty kodi instance pointer");
+ return nullptr;
+ }
+
+ return strdup(CSpecialProtocol::TranslatePath("special://xbmcbinaddons/" + addon->ID()).c_str());
+}
+
+char* Interface_Base::get_user_path(const KODI_ADDON_BACKEND_HDL hdl)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "get_user_path(...) called with empty kodi instance pointer");
+ return nullptr;
+ }
+
+ return strdup(CSpecialProtocol::TranslatePath(addon->Profile()).c_str());
+}
+
+char* Interface_Base::get_temp_path(const KODI_ADDON_BACKEND_HDL hdl)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "get_temp_path(...) called with empty kodi instance pointer");
+ return nullptr;
+ }
+
+ std::string tempPath =
+ URIUtils::AddFileToFolder(CServiceBroker::GetAddonMgr().GetTempAddonBasePath(), addon->ID());
+ tempPath += "-temp";
+ XFILE::CDirectory::Create(tempPath);
+
+ return strdup(CSpecialProtocol::TranslatePath(tempPath).c_str());
+}
+
+char* Interface_Base::get_localized_string(const KODI_ADDON_BACKEND_HDL hdl, long label_id)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "get_localized_string(...) called with empty kodi instance pointer");
+ return nullptr;
+ }
+
+ if (g_application.m_bStop)
+ return nullptr;
+
+ std::string label = g_localizeStrings.GetAddonString(addon->ID(), label_id);
+ if (label.empty())
+ label = g_localizeStrings.Get(label_id);
+ char* buffer = strdup(label.c_str());
+ return buffer;
+}
+
+char* Interface_Base::get_addon_info(const KODI_ADDON_BACKEND_HDL hdl, const char* id)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "get_addon_info(...) called with empty pointer");
+ return nullptr;
+ }
+
+ std::string str;
+ if (StringUtils::CompareNoCase(id, "author") == 0)
+ str = addon->Author();
+ else if (StringUtils::CompareNoCase(id, "changelog") == 0)
+ str = addon->ChangeLog();
+ else if (StringUtils::CompareNoCase(id, "description") == 0)
+ str = addon->Description();
+ else if (StringUtils::CompareNoCase(id, "disclaimer") == 0)
+ str = addon->Disclaimer();
+ else if (StringUtils::CompareNoCase(id, "fanart") == 0)
+ str = addon->FanArt();
+ else if (StringUtils::CompareNoCase(id, "icon") == 0)
+ str = addon->Icon();
+ else if (StringUtils::CompareNoCase(id, "id") == 0)
+ str = addon->ID();
+ else if (StringUtils::CompareNoCase(id, "name") == 0)
+ str = addon->Name();
+ else if (StringUtils::CompareNoCase(id, "path") == 0)
+ str = addon->Path();
+ else if (StringUtils::CompareNoCase(id, "profile") == 0)
+ str = addon->Profile();
+ else if (StringUtils::CompareNoCase(id, "summary") == 0)
+ str = addon->Summary();
+ else if (StringUtils::CompareNoCase(id, "type") == 0)
+ str = ADDON::CAddonInfo::TranslateType(addon->Type());
+ else if (StringUtils::CompareNoCase(id, "version") == 0)
+ str = addon->Version().asString();
+ else
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - add-on '{}' requests invalid id '{}'", __func__,
+ addon->Name(), id);
+ return nullptr;
+ }
+
+ char* buffer = strdup(str.c_str());
+ return buffer;
+}
+
+bool Interface_Base::open_settings_dialog(const KODI_ADDON_BACKEND_HDL hdl)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "open_settings_dialog(...) called with empty kodi instance pointer");
+ return false;
+ }
+
+ // show settings dialog
+ AddonPtr addonInfo;
+ if (!CServiceBroker::GetAddonMgr().GetAddon(addon->ID(), addonInfo, OnlyEnabled::CHOICE_YES))
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - Could not get addon information for '{}'", __func__,
+ addon->ID());
+ return false;
+ }
+
+ return CGUIDialogAddonSettings::ShowForAddon(addonInfo);
+}
+
+bool Interface_Base::is_setting_using_default(const KODI_ADDON_BACKEND_HDL hdl, const char* id)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
+ static_cast<const void*>(id));
+
+ return false;
+ }
+
+ if (!addon->HasSettings())
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
+ addon->Name());
+ return false;
+ }
+
+ auto setting = addon->GetSettings()->GetSetting(id);
+ if (setting == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ return setting->IsDefault();
+}
+
+bool Interface_Base::get_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr || value == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
+ __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
+
+ return false;
+ }
+
+ if (!addon->HasSettings())
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
+ addon->Name());
+ return false;
+ }
+
+ auto setting = addon->GetSettings()->GetSetting(id);
+ if (setting == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ if (setting->GetType() != SettingType::Boolean)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a boolean in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ *value = std::static_pointer_cast<CSettingBool>(setting)->GetValue();
+ return true;
+}
+
+bool Interface_Base::get_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr || value == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
+ __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
+
+ return false;
+ }
+
+ if (!addon->HasSettings())
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
+ addon->Name());
+ return false;
+ }
+
+ auto setting = addon->GetSettings()->GetSetting(id);
+ if (setting == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ if (setting->GetType() != SettingType::Integer && setting->GetType() != SettingType::Number)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a integer in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ if (setting->GetType() == SettingType::Integer)
+ *value = std::static_pointer_cast<CSettingInt>(setting)->GetValue();
+ else
+ *value = static_cast<int>(std::static_pointer_cast<CSettingNumber>(setting)->GetValue());
+ return true;
+}
+
+bool Interface_Base::get_setting_float(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* id,
+ float* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr || value == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
+ __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
+
+ return false;
+ }
+
+ if (!addon->HasSettings())
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
+ addon->Name());
+ return false;
+ }
+
+ auto setting = addon->GetSettings()->GetSetting(id);
+ if (setting == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ if (setting->GetType() != SettingType::Number)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a number in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ *value = static_cast<float>(std::static_pointer_cast<CSettingNumber>(setting)->GetValue());
+ return true;
+}
+
+bool Interface_Base::get_setting_string(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* id,
+ char** value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr || value == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
+ __func__, hdl, static_cast<const void*>(id), static_cast<void*>(value));
+
+ return false;
+ }
+
+ if (!addon->HasSettings())
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - couldn't get settings for add-on '{}'", __func__,
+ addon->Name());
+ return false;
+ }
+
+ auto setting = addon->GetSettings()->GetSetting(id);
+ if (setting == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - can't find setting '{}' in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ if (setting->GetType() != SettingType::String)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - setting '{}' is not a string in '{}'", __func__, id,
+ addon->Name());
+ return false;
+ }
+
+ *value = strdup(std::static_pointer_cast<CSettingString>(setting)->GetValue().c_str());
+ return true;
+}
+
+bool Interface_Base::set_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
+ static_cast<const void*>(id));
+
+ return false;
+ }
+
+ if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
+ value ? "true" : "false"))
+ return true;
+
+ if (!addon->UpdateSettingBool(id, value))
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
+ return false;
+ }
+
+ addon->SaveSettings();
+
+ return true;
+}
+
+bool Interface_Base::set_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
+ static_cast<const void*>(id));
+
+ return false;
+ }
+
+ if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
+ std::to_string(value)))
+ return true;
+
+ if (!addon->UpdateSettingInt(id, value))
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
+ return false;
+ }
+
+ addon->SaveSettings();
+
+ return true;
+}
+
+bool Interface_Base::set_setting_float(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* id,
+ float value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}')", __func__, hdl,
+ static_cast<const void*>(id));
+
+ return false;
+ }
+
+ if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id,
+ StringUtils::Format("{:f}", value)))
+ return true;
+
+ if (!addon->UpdateSettingNumber(id, static_cast<double>(value)))
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
+ return false;
+ }
+
+ addon->SaveSettings();
+
+ return true;
+}
+
+bool Interface_Base::set_setting_string(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* id,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(hdl);
+ if (addon == nullptr || id == nullptr || value == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid data (addon='{}', id='{}', value='{}')",
+ __func__, hdl, static_cast<const void*>(id), static_cast<const void*>(value));
+
+ return false;
+ }
+
+ if (Interface_Base::UpdateSettingInActiveDialog(addon, ADDON_SETTINGS_ID, id, value))
+ return true;
+
+ if (!addon->UpdateSettingString(id, value))
+ {
+ CLog::Log(LOGERROR, "Interface_Base::{} - invalid setting type", __func__);
+ return false;
+ }
+
+ addon->SaveSettings();
+
+ return true;
+}
+
+void Interface_Base::free_string(const KODI_ADDON_BACKEND_HDL hdl, char* str)
+{
+ if (str)
+ free(str);
+}
+
+void Interface_Base::free_string_array(const KODI_ADDON_BACKEND_HDL hdl,
+ char** arr,
+ int numElements)
+{
+ if (arr)
+ {
+ for (int i = 0; i < numElements; ++i)
+ {
+ free(arr[i]);
+ }
+ free(arr);
+ }
+}
+
+void* Interface_Base::get_interface(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* name,
+ const char* version)
+{
+ if (!name || !version)
+ return nullptr;
+
+ void* retval(nullptr);
+
+ for (auto fn : s_registeredInterfaces)
+ if ((retval = fn(name, version)))
+ break;
+
+ return retval;
+}
+
+//@}
+
+} // namespace ADDON
diff --git a/xbmc/addons/interfaces/AddonBase.h b/xbmc/addons/interfaces/AddonBase.h
new file mode 100644
index 0000000..6dcc53c
--- /dev/null
+++ b/xbmc/addons/interfaces/AddonBase.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2005-2020 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/IAddon.h"
+#include "addons/kodi-dev-kit/include/kodi/c-api/addon_base.h"
+
+extern "C"
+{
+namespace ADDON
+{
+
+typedef void* (*ADDON_GET_INTERFACE_FN)(const std::string& name, const std::string& version);
+
+class CAddonDll;
+
+/*!
+ * @brief Global general Add-on to Kodi callback functions
+ *
+ * To hold general functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/General.h"
+ */
+struct Interface_Base
+{
+ static bool InitInterface(CAddonDll* addon,
+ AddonGlobalInterface& addonInterface,
+ KODI_ADDON_INSTANCE_STRUCT* firstKodiInstance);
+ static void DeInitInterface(AddonGlobalInterface& addonInterface);
+ static void RegisterInterface(ADDON_GET_INTERFACE_FN fn);
+ static bool UpdateSettingInActiveDialog(CAddonDll* addon,
+ AddonInstanceId instanceId,
+ const char* id,
+ const std::string& value);
+
+ static std::vector<ADDON_GET_INTERFACE_FN> s_registeredInterfaces;
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void addon_log_msg(const KODI_ADDON_BACKEND_HDL hdl,
+ const int addonLogLevel,
+ const char* strMessage);
+ static char* get_type_version(const KODI_ADDON_BACKEND_HDL hdl, int type);
+ static char* get_addon_path(const KODI_ADDON_BACKEND_HDL hdl);
+ static char* get_lib_path(const KODI_ADDON_BACKEND_HDL hdl);
+ static char* get_user_path(const KODI_ADDON_BACKEND_HDL hdl);
+ static char* get_temp_path(const KODI_ADDON_BACKEND_HDL hdl);
+ static char* get_localized_string(const KODI_ADDON_BACKEND_HDL hdl, long label_id);
+ static char* get_addon_info(const KODI_ADDON_BACKEND_HDL hdl, const char* id);
+ static bool open_settings_dialog(const KODI_ADDON_BACKEND_HDL hdl);
+ static bool is_setting_using_default(const KODI_ADDON_BACKEND_HDL hdl, const char* id);
+ static bool get_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool* value);
+ static bool get_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int* value);
+ static bool get_setting_float(const KODI_ADDON_BACKEND_HDL hdl, const char* id, float* value);
+ static bool get_setting_string(const KODI_ADDON_BACKEND_HDL hdl, const char* id, char** value);
+ static bool set_setting_bool(const KODI_ADDON_BACKEND_HDL hdl, const char* id, bool value);
+ static bool set_setting_int(const KODI_ADDON_BACKEND_HDL hdl, const char* id, int value);
+ static bool set_setting_float(const KODI_ADDON_BACKEND_HDL hdl, const char* id, float value);
+ static bool set_setting_string(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* id,
+ const char* value);
+ static void free_string(const KODI_ADDON_BACKEND_HDL hdl, char* str);
+ static void free_string_array(const KODI_ADDON_BACKEND_HDL hdl, char** arr, int numElements);
+ static void* get_interface(const KODI_ADDON_BACKEND_HDL hdl,
+ const char* name,
+ const char* version);
+ //@}
+};
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/AudioEngine.cpp b/xbmc/addons/interfaces/AudioEngine.cpp
new file mode 100644
index 0000000..0efcc07
--- /dev/null
+++ b/xbmc/addons/interfaces/AudioEngine.cpp
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "AudioEngine.h"
+
+#include "ServiceBroker.h"
+#include "addons/kodi-dev-kit/include/kodi/AddonBase.h"
+#include "cores/AudioEngine/Interfaces/AE.h"
+#include "cores/AudioEngine/Interfaces/AEStream.h"
+#include "cores/AudioEngine/Utils/AEStreamData.h"
+#include "utils/log.h"
+
+using namespace kodi; // addon-dev-kit namespace
+using namespace kodi::audioengine; // addon-dev-kit namespace
+
+namespace ADDON
+{
+
+void Interface_AudioEngine::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_audioengine = new AddonToKodiFuncTable_kodi_audioengine();
+
+ // write KODI audio DSP specific add-on function addresses to callback table
+ addonInterface->toKodi->kodi_audioengine->make_stream = audioengine_make_stream;
+ addonInterface->toKodi->kodi_audioengine->free_stream = audioengine_free_stream;
+ addonInterface->toKodi->kodi_audioengine->get_current_sink_format = get_current_sink_format;
+
+ // AEStream add-on function callback table
+ addonInterface->toKodi->kodi_audioengine->aestream_get_space = aestream_get_space;
+ addonInterface->toKodi->kodi_audioengine->aestream_add_data = aestream_add_data;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_delay = aestream_get_delay;
+ addonInterface->toKodi->kodi_audioengine->aestream_is_buffering = aestream_is_buffering;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_cache_time = aestream_get_cache_time;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_cache_total = aestream_get_cache_total;
+ addonInterface->toKodi->kodi_audioengine->aestream_pause = aestream_pause;
+ addonInterface->toKodi->kodi_audioengine->aestream_resume = aestream_resume;
+ addonInterface->toKodi->kodi_audioengine->aestream_drain = aestream_drain;
+ addonInterface->toKodi->kodi_audioengine->aestream_is_draining = aestream_is_draining;
+ addonInterface->toKodi->kodi_audioengine->aestream_is_drained = aestream_is_drained;
+ addonInterface->toKodi->kodi_audioengine->aestream_flush = aestream_flush;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_volume = aestream_get_volume;
+ addonInterface->toKodi->kodi_audioengine->aestream_set_volume = aestream_set_volume;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_amplification = aestream_get_amplification;
+ addonInterface->toKodi->kodi_audioengine->aestream_set_amplification = aestream_set_amplification;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_frame_size = aestream_get_frame_size;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_channel_count = aestream_get_channel_count;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_sample_rate = aestream_get_sample_rate;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_data_format = aestream_get_data_format;
+ addonInterface->toKodi->kodi_audioengine->aestream_get_resample_ratio =
+ aestream_get_resample_ratio;
+ addonInterface->toKodi->kodi_audioengine->aestream_set_resample_ratio =
+ aestream_set_resample_ratio;
+}
+
+void Interface_AudioEngine::DeInit(AddonGlobalInterface* addonInterface)
+{
+ if (addonInterface->toKodi) /* <-- Safe check, needed so long old addon way is present */
+ {
+ delete addonInterface->toKodi->kodi_audioengine;
+ addonInterface->toKodi->kodi_audioengine = nullptr;
+ }
+}
+
+AEChannel Interface_AudioEngine::TranslateAEChannelToKodi(AudioEngineChannel channel)
+{
+ switch (channel)
+ {
+ case AUDIOENGINE_CH_RAW:
+ return AE_CH_RAW;
+ case AUDIOENGINE_CH_FL:
+ return AE_CH_FL;
+ case AUDIOENGINE_CH_FR:
+ return AE_CH_FR;
+ case AUDIOENGINE_CH_FC:
+ return AE_CH_FC;
+ case AUDIOENGINE_CH_LFE:
+ return AE_CH_LFE;
+ case AUDIOENGINE_CH_BL:
+ return AE_CH_BL;
+ case AUDIOENGINE_CH_BR:
+ return AE_CH_BR;
+ case AUDIOENGINE_CH_FLOC:
+ return AE_CH_FLOC;
+ case AUDIOENGINE_CH_FROC:
+ return AE_CH_FROC;
+ case AUDIOENGINE_CH_BC:
+ return AE_CH_BC;
+ case AUDIOENGINE_CH_SL:
+ return AE_CH_SL;
+ case AUDIOENGINE_CH_SR:
+ return AE_CH_SR;
+ case AUDIOENGINE_CH_TFL:
+ return AE_CH_TFL;
+ case AUDIOENGINE_CH_TFR:
+ return AE_CH_TFR;
+ case AUDIOENGINE_CH_TFC:
+ return AE_CH_TFC;
+ case AUDIOENGINE_CH_TC:
+ return AE_CH_TC;
+ case AUDIOENGINE_CH_TBL:
+ return AE_CH_TBL;
+ case AUDIOENGINE_CH_TBR:
+ return AE_CH_TBR;
+ case AUDIOENGINE_CH_TBC:
+ return AE_CH_TBC;
+ case AUDIOENGINE_CH_BLOC:
+ return AE_CH_BLOC;
+ case AUDIOENGINE_CH_BROC:
+ return AE_CH_BROC;
+ case AUDIOENGINE_CH_MAX:
+ return AE_CH_MAX;
+ case AUDIOENGINE_CH_NULL:
+ default:
+ return AE_CH_NULL;
+ }
+}
+
+AudioEngineChannel Interface_AudioEngine::TranslateAEChannelToAddon(AEChannel channel)
+{
+ switch (channel)
+ {
+ case AE_CH_RAW:
+ return AUDIOENGINE_CH_RAW;
+ case AE_CH_FL:
+ return AUDIOENGINE_CH_FL;
+ case AE_CH_FR:
+ return AUDIOENGINE_CH_FR;
+ case AE_CH_FC:
+ return AUDIOENGINE_CH_FC;
+ case AE_CH_LFE:
+ return AUDIOENGINE_CH_LFE;
+ case AE_CH_BL:
+ return AUDIOENGINE_CH_BL;
+ case AE_CH_BR:
+ return AUDIOENGINE_CH_BR;
+ case AE_CH_FLOC:
+ return AUDIOENGINE_CH_FLOC;
+ case AE_CH_FROC:
+ return AUDIOENGINE_CH_FROC;
+ case AE_CH_BC:
+ return AUDIOENGINE_CH_BC;
+ case AE_CH_SL:
+ return AUDIOENGINE_CH_SL;
+ case AE_CH_SR:
+ return AUDIOENGINE_CH_SR;
+ case AE_CH_TFL:
+ return AUDIOENGINE_CH_TFL;
+ case AE_CH_TFR:
+ return AUDIOENGINE_CH_TFR;
+ case AE_CH_TFC:
+ return AUDIOENGINE_CH_TFC;
+ case AE_CH_TC:
+ return AUDIOENGINE_CH_TC;
+ case AE_CH_TBL:
+ return AUDIOENGINE_CH_TBL;
+ case AE_CH_TBR:
+ return AUDIOENGINE_CH_TBR;
+ case AE_CH_TBC:
+ return AUDIOENGINE_CH_TBC;
+ case AE_CH_BLOC:
+ return AUDIOENGINE_CH_BLOC;
+ case AE_CH_BROC:
+ return AUDIOENGINE_CH_BROC;
+ case AE_CH_MAX:
+ return AUDIOENGINE_CH_MAX;
+ case AE_CH_NULL:
+ default:
+ return AUDIOENGINE_CH_NULL;
+ }
+}
+
+AEDataFormat Interface_AudioEngine::TranslateAEFormatToKodi(AudioEngineDataFormat format)
+{
+ switch (format)
+ {
+ case AUDIOENGINE_FMT_U8:
+ return AE_FMT_U8;
+ case AUDIOENGINE_FMT_S16BE:
+ return AE_FMT_S16BE;
+ case AUDIOENGINE_FMT_S16LE:
+ return AE_FMT_S16LE;
+ case AUDIOENGINE_FMT_S16NE:
+ return AE_FMT_S16NE;
+ case AUDIOENGINE_FMT_S32BE:
+ return AE_FMT_S32BE;
+ case AUDIOENGINE_FMT_S32LE:
+ return AE_FMT_S32LE;
+ case AUDIOENGINE_FMT_S32NE:
+ return AE_FMT_S32NE;
+ case AUDIOENGINE_FMT_S24BE4:
+ return AE_FMT_S24BE4;
+ case AUDIOENGINE_FMT_S24LE4:
+ return AE_FMT_S24LE4;
+ case AUDIOENGINE_FMT_S24NE4:
+ return AE_FMT_S24NE4;
+ case AUDIOENGINE_FMT_S24NE4MSB:
+ return AE_FMT_S24NE4MSB;
+ case AUDIOENGINE_FMT_S24BE3:
+ return AE_FMT_S24BE3;
+ case AUDIOENGINE_FMT_S24LE3:
+ return AE_FMT_S24LE3;
+ case AUDIOENGINE_FMT_S24NE3:
+ return AE_FMT_S24NE3;
+ case AUDIOENGINE_FMT_DOUBLE:
+ return AE_FMT_DOUBLE;
+ case AUDIOENGINE_FMT_FLOAT:
+ return AE_FMT_FLOAT;
+ case AUDIOENGINE_FMT_RAW:
+ return AE_FMT_RAW;
+ case AUDIOENGINE_FMT_U8P:
+ return AE_FMT_U8P;
+ case AUDIOENGINE_FMT_S16NEP:
+ return AE_FMT_S16NEP;
+ case AUDIOENGINE_FMT_S32NEP:
+ return AE_FMT_S32NEP;
+ case AUDIOENGINE_FMT_S24NE4P:
+ return AE_FMT_S24NE4P;
+ case AUDIOENGINE_FMT_S24NE4MSBP:
+ return AE_FMT_S24NE4MSBP;
+ case AUDIOENGINE_FMT_S24NE3P:
+ return AE_FMT_S24NE3P;
+ case AUDIOENGINE_FMT_DOUBLEP:
+ return AE_FMT_DOUBLEP;
+ case AUDIOENGINE_FMT_FLOATP:
+ return AE_FMT_FLOATP;
+ case AUDIOENGINE_FMT_MAX:
+ return AE_FMT_MAX;
+ case AUDIOENGINE_FMT_INVALID:
+ default:
+ return AE_FMT_INVALID;
+ }
+}
+
+AudioEngineDataFormat Interface_AudioEngine::TranslateAEFormatToAddon(AEDataFormat format)
+{
+ switch (format)
+ {
+ case AE_FMT_U8:
+ return AUDIOENGINE_FMT_U8;
+ case AE_FMT_S16BE:
+ return AUDIOENGINE_FMT_S16BE;
+ case AE_FMT_S16LE:
+ return AUDIOENGINE_FMT_S16LE;
+ case AE_FMT_S16NE:
+ return AUDIOENGINE_FMT_S16NE;
+ case AE_FMT_S32BE:
+ return AUDIOENGINE_FMT_S32BE;
+ case AE_FMT_S32LE:
+ return AUDIOENGINE_FMT_S32LE;
+ case AE_FMT_S32NE:
+ return AUDIOENGINE_FMT_S32NE;
+ case AE_FMT_S24BE4:
+ return AUDIOENGINE_FMT_S24BE4;
+ case AE_FMT_S24LE4:
+ return AUDIOENGINE_FMT_S24LE4;
+ case AE_FMT_S24NE4:
+ return AUDIOENGINE_FMT_S24NE4;
+ case AE_FMT_S24NE4MSB:
+ return AUDIOENGINE_FMT_S24NE4MSB;
+ case AE_FMT_S24BE3:
+ return AUDIOENGINE_FMT_S24BE3;
+ case AE_FMT_S24LE3:
+ return AUDIOENGINE_FMT_S24LE3;
+ case AE_FMT_S24NE3:
+ return AUDIOENGINE_FMT_S24NE3;
+ case AE_FMT_DOUBLE:
+ return AUDIOENGINE_FMT_DOUBLE;
+ case AE_FMT_FLOAT:
+ return AUDIOENGINE_FMT_FLOAT;
+ case AE_FMT_RAW:
+ return AUDIOENGINE_FMT_RAW;
+ case AE_FMT_U8P:
+ return AUDIOENGINE_FMT_U8P;
+ case AE_FMT_S16NEP:
+ return AUDIOENGINE_FMT_S16NEP;
+ case AE_FMT_S32NEP:
+ return AUDIOENGINE_FMT_S32NEP;
+ case AE_FMT_S24NE4P:
+ return AUDIOENGINE_FMT_S24NE4P;
+ case AE_FMT_S24NE4MSBP:
+ return AUDIOENGINE_FMT_S24NE4MSBP;
+ case AE_FMT_S24NE3P:
+ return AUDIOENGINE_FMT_S24NE3P;
+ case AE_FMT_DOUBLEP:
+ return AUDIOENGINE_FMT_DOUBLEP;
+ case AE_FMT_FLOATP:
+ return AUDIOENGINE_FMT_FLOATP;
+ case AE_FMT_MAX:
+ return AUDIOENGINE_FMT_MAX;
+ case AE_FMT_INVALID:
+ default:
+ return AUDIOENGINE_FMT_INVALID;
+ }
+}
+
+AEStreamHandle* Interface_AudioEngine::audioengine_make_stream(void* kodiBase,
+ AUDIO_ENGINE_FORMAT* streamFormat,
+ unsigned int options)
+{
+ if (!kodiBase || !streamFormat)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamFormat='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamFormat));
+ return nullptr;
+ }
+
+ IAE* engine = CServiceBroker::GetActiveAE();
+ if (!engine)
+ return nullptr;
+
+ CAEChannelInfo layout;
+ for (unsigned int ch = 0; ch < AUDIOENGINE_CH_MAX; ++ch)
+ {
+ if (streamFormat->m_channels[ch] == AUDIOENGINE_CH_NULL)
+ break;
+ layout += TranslateAEChannelToKodi(streamFormat->m_channels[ch]);
+ }
+
+ AEAudioFormat format;
+ format.m_channelLayout = layout;
+ format.m_dataFormat = TranslateAEFormatToKodi(streamFormat->m_dataFormat);
+ format.m_sampleRate = streamFormat->m_sampleRate;
+
+ /* Translate addon options to kodi's options */
+ int kodiOption = 0;
+ if (options & AUDIO_STREAM_FORCE_RESAMPLE)
+ kodiOption |= AESTREAM_FORCE_RESAMPLE;
+ if (options & AUDIO_STREAM_PAUSED)
+ kodiOption |= AESTREAM_PAUSED;
+ if (options & AUDIO_STREAM_AUTOSTART)
+ kodiOption |= AESTREAM_AUTOSTART;
+
+ return engine->MakeStream(format, kodiOption).release();
+}
+
+void Interface_AudioEngine::audioengine_free_stream(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ IAE* engine = CServiceBroker::GetActiveAE();
+ if (engine)
+ engine->FreeStream(static_cast<IAEStream*>(streamHandle), true);
+}
+
+bool Interface_AudioEngine::get_current_sink_format(void* kodiBase, AUDIO_ENGINE_FORMAT* format)
+{
+ if (!kodiBase || !format)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', format='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(format));
+ return false;
+ }
+
+ IAE* engine = CServiceBroker::GetActiveAE();
+ if (!engine)
+ return false;
+
+ AEAudioFormat sinkFormat;
+ if (!engine->GetCurrentSinkFormat(sinkFormat))
+ {
+ CLog::Log(LOGERROR, "Interface_AudioEngine::{} - failed to get current sink format from AE!",
+ __FUNCTION__);
+ return false;
+ }
+
+ format->m_dataFormat = TranslateAEFormatToAddon(sinkFormat.m_dataFormat);
+ format->m_sampleRate = sinkFormat.m_sampleRate;
+ format->m_frames = sinkFormat.m_frames;
+ format->m_frameSize = sinkFormat.m_frameSize;
+ format->m_channelCount = sinkFormat.m_channelLayout.Count();
+ for (unsigned int ch = 0; ch < format->m_channelCount && ch < AUDIOENGINE_CH_MAX; ++ch)
+ {
+ format->m_channels[ch] = TranslateAEChannelToAddon(sinkFormat.m_channelLayout[ch]);
+ }
+
+ return true;
+}
+
+unsigned int Interface_AudioEngine::aestream_get_space(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return 0;
+ }
+
+ return static_cast<IAEStream*>(streamHandle)->GetSpace();
+}
+
+unsigned int Interface_AudioEngine::aestream_add_data(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ uint8_t* const* data,
+ unsigned int offset,
+ unsigned int frames,
+ double pts,
+ bool hasDownmix,
+ double centerMixLevel)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return 0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return 0;
+
+ IAEStream::ExtData extData;
+ extData.pts = pts;
+ extData.hasDownmix = hasDownmix;
+ extData.centerMixLevel = centerMixLevel;
+ return static_cast<IAEStream*>(streamHandle)->AddData(data, offset, frames, &extData);
+}
+
+double Interface_AudioEngine::aestream_get_delay(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetDelay();
+}
+
+bool Interface_AudioEngine::aestream_is_buffering(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return false;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return false;
+
+ return static_cast<IAEStream*>(streamHandle)->IsBuffering();
+}
+
+double Interface_AudioEngine::aestream_get_cache_time(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetCacheTime();
+}
+
+double Interface_AudioEngine::aestream_get_cache_total(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetCacheTotal();
+}
+
+void Interface_AudioEngine::aestream_pause(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->Pause();
+}
+
+void Interface_AudioEngine::aestream_resume(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ static_cast<IAEStream*>(streamHandle)->Resume();
+}
+
+void Interface_AudioEngine::aestream_drain(void* kodiBase, AEStreamHandle* streamHandle, bool wait)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->Drain(wait);
+}
+
+bool Interface_AudioEngine::aestream_is_draining(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return false;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return false;
+
+ return static_cast<IAEStream*>(streamHandle)->IsDraining();
+}
+
+bool Interface_AudioEngine::aestream_is_drained(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return false;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return false;
+
+ return static_cast<IAEStream*>(streamHandle)->IsDrained();
+}
+
+void Interface_AudioEngine::aestream_flush(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->Flush();
+}
+
+float Interface_AudioEngine::aestream_get_volume(void* kodiBase, AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0f;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0f;
+
+ return static_cast<IAEStream*>(streamHandle)->GetVolume();
+}
+
+void Interface_AudioEngine::aestream_set_volume(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ float volume)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->SetVolume(volume);
+}
+
+float Interface_AudioEngine::aestream_get_amplification(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0f;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0f;
+
+ return static_cast<IAEStream*>(streamHandle)->GetAmplification();
+}
+
+void Interface_AudioEngine::aestream_set_amplification(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ float amplify)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->SetAmplification(amplify);
+}
+
+unsigned int Interface_AudioEngine::aestream_get_frame_size(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return 0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return 0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetFrameSize();
+}
+
+unsigned int Interface_AudioEngine::aestream_get_channel_count(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return 0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return 0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetChannelCount();
+}
+
+unsigned int Interface_AudioEngine::aestream_get_sample_rate(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return 0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return 0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetSampleRate();
+}
+
+AudioEngineDataFormat Interface_AudioEngine::aestream_get_data_format(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return AUDIOENGINE_FMT_INVALID;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return AUDIOENGINE_FMT_INVALID;
+
+ return TranslateAEFormatToAddon(static_cast<IAEStream*>(streamHandle)->GetDataFormat());
+}
+
+double Interface_AudioEngine::aestream_get_resample_ratio(void* kodiBase,
+ AEStreamHandle* streamHandle)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return -1.0;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return -1.0;
+
+ return static_cast<IAEStream*>(streamHandle)->GetResampleRatio();
+}
+
+void Interface_AudioEngine::aestream_set_resample_ratio(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ double ratio)
+{
+ if (!kodiBase || !streamHandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_AudioEngine::{} - invalid stream data (kodiBase='{}', streamHandle='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(streamHandle));
+ return;
+ }
+
+ if (!CServiceBroker::GetActiveAE())
+ return;
+
+ static_cast<IAEStream*>(streamHandle)->SetResampleRatio(ratio);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/AudioEngine.h b/xbmc/addons/interfaces/AudioEngine.h
new file mode 100644
index 0000000..3700931
--- /dev/null
+++ b/xbmc/addons/interfaces/AudioEngine.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/AudioEngine.h"
+#include "cores/AudioEngine/Utils/AEChannelData.h"
+
+extern "C"
+{
+namespace ADDON
+{
+
+struct Interface_AudioEngine
+{
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /**
+ * @brief Translation functions to separate Kodi and addons
+ *
+ * This thought to make it more safe for cases as something changed inside
+ * Kodi, addons overseen and breaks API, further to have on addons a better
+ * documentation about this parts.
+ */
+ //@{
+ static AEChannel TranslateAEChannelToKodi(AudioEngineChannel channel);
+ static AudioEngineChannel TranslateAEChannelToAddon(AEChannel channel);
+ static AEDataFormat TranslateAEFormatToKodi(AudioEngineDataFormat format);
+ static AudioEngineDataFormat TranslateAEFormatToAddon(AEDataFormat format);
+ //@}
+
+ /**
+ * Creates and returns a new handle to an IAEStream in the format specified, this function should never fail
+ * @param[in] streamFormat Format to use for stream
+ * @param[in] options A bit field of stream options (see: enum AEStreamOptions)
+ * @return a new Handle to an IAEStream that will accept data in the requested format
+ */
+ static AEStreamHandle* audioengine_make_stream(void* kodiBase,
+ AUDIO_ENGINE_FORMAT* streamFormat,
+ unsigned int options);
+
+ /**
+ * This method will remove the specified stream from the engine.
+ * For OSX/IOS this is essential to reconfigure the audio output.
+ * @param[in] streamHandle The stream to be altered
+ */
+ static void audioengine_free_stream(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Get the current sink data format
+ *
+ * @param[in] sinkFormat sink data format. For more details see AUDIO_ENGINE_FORMAT.
+ * @return Returns true on success, else false.
+ */
+ static bool get_current_sink_format(void* kodiBase, AUDIO_ENGINE_FORMAT* sinkFormat);
+
+ /**
+ * Returns the amount of space available in the stream
+ * @return The number of bytes AddData will consume
+ */
+ static unsigned int aestream_get_space(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Add planar or interleaved PCM data to the stream
+ * @param[in] data array of pointers to the planes
+ * @param[in] offset to frame in frames
+ * @param[in] frames number of frames
+ * @return The number of frames consumed
+ */
+ static unsigned int aestream_add_data(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ uint8_t* const* data,
+ unsigned int offset,
+ unsigned int frames,
+ double pts,
+ bool hasDownmix,
+ double centerMixLevel);
+
+ /**
+ * Returns the time in seconds that it will take
+ * for the next added packet to be heard from the speakers.
+ * @return seconds
+ */
+ static double aestream_get_delay(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns if the stream is buffering
+ * @return True if the stream is buffering
+ */
+ static bool aestream_is_buffering(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns the time in seconds that it will take
+ * to underrun the cache if no sample is added.
+ * @return seconds
+ */
+ static double aestream_get_cache_time(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns the total time in seconds of the cache
+ * @return seconds
+ */
+ static double aestream_get_cache_total(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Pauses the stream playback
+ */
+ static void aestream_pause(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Resumes the stream after pausing
+ */
+ static void aestream_resume(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Start draining the stream
+ * @note Once called AddData will not consume more data.
+ */
+ static void aestream_drain(void* kodiBase, AEStreamHandle* streamHandle, bool wait);
+
+ /**
+ * Returns true if the is stream draining
+ */
+ static bool aestream_is_draining(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns true if the is stream has finished draining
+ */
+ static bool aestream_is_drained(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Flush all buffers dropping the audio data
+ */
+ static void aestream_flush(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Return the stream's current volume level
+ * @return The volume level between 0.0 and 1.0
+ */
+ static float aestream_get_volume(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Set the stream's volume level
+ * @param volume The new volume level between 0.0 and 1.0
+ */
+ static void aestream_set_volume(void* kodiBase, AEStreamHandle* streamHandle, float volume);
+
+ /**
+ * Gets the stream's volume amplification in linear units.
+ * @return The volume amplification factor between 1.0 and 1000.0
+ */
+ static float aestream_get_amplification(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Sets the stream's volume amplification in linear units.
+ * @param amplify The volume amplification factor between 1.0 and 1000.0
+ */
+ static void aestream_set_amplification(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ float amplify);
+
+ /**
+ * Returns the size of one audio frame in bytes (channelCount * resolution)
+ * @return The size in bytes of one frame
+ */
+ static unsigned int aestream_get_frame_size(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns the number of channels the stream is configured to accept
+ * @return The channel count
+ */
+ static unsigned int aestream_get_channel_count(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Returns the stream's sample rate, if the stream is using a dynamic sample
+ * rate, this value will NOT reflect any changes made by calls to SetResampleRatio()
+ * @return The stream's sample rate (eg, 48000)
+ */
+ static unsigned int aestream_get_sample_rate(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Return the data format the stream has been configured with
+ * @return The stream's data format (eg, AE_FMT_S16LE)
+ */
+ static AudioEngineDataFormat aestream_get_data_format(void* kodiBase,
+ AEStreamHandle* streamHandle);
+
+ /**
+ * Return the resample ratio
+ * @note This will return an undefined value if the stream is not resampling
+ * @return the current resample ratio or undefined if the stream is not resampling
+ */
+ static double aestream_get_resample_ratio(void* kodiBase, AEStreamHandle* streamHandle);
+
+ /**
+ * Sets the resample ratio
+ * @note This function may return false if the stream is not resampling, if you wish to use this be sure to set the AESTREAM_FORCE_RESAMPLE option
+ * @param[in] ratio the new sample rate ratio, calculated by ((double)desiredRate / (double)GetSampleRate())
+ */
+ static void aestream_set_resample_ratio(void* kodiBase,
+ AEStreamHandle* streamHandle,
+ double ratio);
+};
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/CMakeLists.txt b/xbmc/addons/interfaces/CMakeLists.txt
new file mode 100644
index 0000000..8e58bb6
--- /dev/null
+++ b/xbmc/addons/interfaces/CMakeLists.txt
@@ -0,0 +1,18 @@
+set(SOURCES AddonBase.cpp
+ AudioEngine.cpp
+ General.cpp
+ Filesystem.cpp
+ Network.cpp)
+
+set(HEADERS AddonBase.h
+ AudioEngine.h
+ General.h
+ Filesystem.h
+ Network.h)
+
+if(CORE_SYSTEM_NAME STREQUAL android)
+ list(APPEND SOURCES platform/android/System.cpp)
+ list(APPEND HEADERS platform/android/System.h)
+endif()
+
+core_add_library(addons_interfaces)
diff --git a/xbmc/addons/interfaces/Filesystem.cpp b/xbmc/addons/interfaces/Filesystem.cpp
new file mode 100644
index 0000000..c063b48
--- /dev/null
+++ b/xbmc/addons/interfaces/Filesystem.cpp
@@ -0,0 +1,1181 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Filesystem.h"
+
+#include "FileItem.h"
+#include "Util.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "filesystem/CurlFile.h"
+#include "filesystem/Directory.h"
+#include "filesystem/File.h"
+#include "filesystem/SpecialProtocol.h"
+#include "platform/Filesystem.h"
+#include "utils/Crc32.h"
+#include "utils/HttpHeader.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/log.h"
+
+#include <vector>
+
+#if defined(TARGET_WINDOWS)
+#ifndef S_IFLNK
+#define S_IFLNK 0120000
+#endif
+#ifndef S_ISBLK
+#define S_ISBLK(m) (0)
+#endif
+#ifndef S_ISSOCK
+#define S_ISSOCK(m) (0)
+#endif
+#ifndef S_ISLNK
+#define S_ISLNK(m) ((m & S_IFLNK) != 0)
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(m) ((m & _S_IFCHR) != 0)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) ((m & _S_IFDIR) != 0)
+#endif
+#ifndef S_ISFIFO
+#define S_ISFIFO(m) ((m & _S_IFIFO) != 0)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(m) ((m & _S_IFREG) != 0)
+#endif
+#endif
+
+using namespace kodi; // addon-dev-kit namespace
+using namespace XFILE;
+
+extern "C"
+{
+namespace ADDON
+{
+
+void Interface_Filesystem::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_filesystem = new AddonToKodiFuncTable_kodi_filesystem();
+
+ addonInterface->toKodi->kodi_filesystem->can_open_directory = can_open_directory;
+ addonInterface->toKodi->kodi_filesystem->create_directory = create_directory;
+ addonInterface->toKodi->kodi_filesystem->directory_exists = directory_exists;
+ addonInterface->toKodi->kodi_filesystem->remove_directory = remove_directory;
+ addonInterface->toKodi->kodi_filesystem->remove_directory_recursive = remove_directory_recursive;
+ addonInterface->toKodi->kodi_filesystem->get_directory = get_directory;
+ addonInterface->toKodi->kodi_filesystem->free_directory = free_directory;
+
+ addonInterface->toKodi->kodi_filesystem->file_exists = file_exists;
+ addonInterface->toKodi->kodi_filesystem->stat_file = stat_file;
+ addonInterface->toKodi->kodi_filesystem->delete_file = delete_file;
+ addonInterface->toKodi->kodi_filesystem->rename_file = rename_file;
+ addonInterface->toKodi->kodi_filesystem->copy_file = copy_file;
+ addonInterface->toKodi->kodi_filesystem->get_file_md5 = get_file_md5;
+ addonInterface->toKodi->kodi_filesystem->get_cache_thumb_name = get_cache_thumb_name;
+ addonInterface->toKodi->kodi_filesystem->make_legal_filename = make_legal_filename;
+ addonInterface->toKodi->kodi_filesystem->make_legal_path = make_legal_path;
+ addonInterface->toKodi->kodi_filesystem->translate_special_protocol = translate_special_protocol;
+ addonInterface->toKodi->kodi_filesystem->get_disk_space = get_disk_space;
+ addonInterface->toKodi->kodi_filesystem->is_internet_stream = is_internet_stream;
+ addonInterface->toKodi->kodi_filesystem->is_on_lan = is_on_lan;
+ addonInterface->toKodi->kodi_filesystem->is_remote = is_remote;
+ addonInterface->toKodi->kodi_filesystem->is_local = is_local;
+ addonInterface->toKodi->kodi_filesystem->is_url = is_url;
+ addonInterface->toKodi->kodi_filesystem->get_http_header = get_http_header;
+ addonInterface->toKodi->kodi_filesystem->get_mime_type = get_mime_type;
+ addonInterface->toKodi->kodi_filesystem->get_content_type = get_content_type;
+ addonInterface->toKodi->kodi_filesystem->get_cookies = get_cookies;
+
+ addonInterface->toKodi->kodi_filesystem->http_header_create = http_header_create;
+ addonInterface->toKodi->kodi_filesystem->http_header_free = http_header_free;
+
+ addonInterface->toKodi->kodi_filesystem->open_file = open_file;
+ addonInterface->toKodi->kodi_filesystem->open_file_for_write = open_file_for_write;
+ addonInterface->toKodi->kodi_filesystem->read_file = read_file;
+ addonInterface->toKodi->kodi_filesystem->read_file_string = read_file_string;
+ addonInterface->toKodi->kodi_filesystem->write_file = write_file;
+ addonInterface->toKodi->kodi_filesystem->flush_file = flush_file;
+ addonInterface->toKodi->kodi_filesystem->seek_file = seek_file;
+ addonInterface->toKodi->kodi_filesystem->truncate_file = truncate_file;
+ addonInterface->toKodi->kodi_filesystem->get_file_position = get_file_position;
+ addonInterface->toKodi->kodi_filesystem->get_file_length = get_file_length;
+ addonInterface->toKodi->kodi_filesystem->get_file_download_speed = get_file_download_speed;
+ addonInterface->toKodi->kodi_filesystem->close_file = close_file;
+ addonInterface->toKodi->kodi_filesystem->get_file_chunk_size = get_file_chunk_size;
+ addonInterface->toKodi->kodi_filesystem->io_control_get_seek_possible =
+ io_control_get_seek_possible;
+ addonInterface->toKodi->kodi_filesystem->io_control_get_cache_status =
+ io_control_get_cache_status;
+ addonInterface->toKodi->kodi_filesystem->io_control_set_cache_rate = io_control_set_cache_rate;
+ addonInterface->toKodi->kodi_filesystem->io_control_set_retry = io_control_set_retry;
+ addonInterface->toKodi->kodi_filesystem->get_property_values = get_property_values;
+
+ addonInterface->toKodi->kodi_filesystem->curl_create = curl_create;
+ addonInterface->toKodi->kodi_filesystem->curl_add_option = curl_add_option;
+ addonInterface->toKodi->kodi_filesystem->curl_open = curl_open;
+}
+
+void Interface_Filesystem::DeInit(AddonGlobalInterface* addonInterface)
+{
+ if (addonInterface->toKodi) /* <-- Safe check, needed so long old addon way is present */
+ {
+ delete addonInterface->toKodi->kodi_filesystem;
+ addonInterface->toKodi->kodi_filesystem = nullptr;
+ }
+}
+
+unsigned int Interface_Filesystem::TranslateFileReadBitsToKodi(unsigned int addonFlags)
+{
+ unsigned int kodiFlags = 0;
+
+ if (addonFlags & ADDON_READ_TRUNCATED)
+ kodiFlags |= READ_TRUNCATED;
+ if (addonFlags & ADDON_READ_CHUNKED)
+ kodiFlags |= READ_CHUNKED;
+ if (addonFlags & ADDON_READ_CACHED)
+ kodiFlags |= READ_CACHED;
+ if (addonFlags & ADDON_READ_NO_CACHE)
+ kodiFlags |= READ_NO_CACHE;
+ if (addonFlags & ADDON_READ_BITRATE)
+ kodiFlags |= READ_BITRATE;
+ if (addonFlags & ADDON_READ_MULTI_STREAM)
+ kodiFlags |= READ_MULTI_STREAM;
+ if (addonFlags & ADDON_READ_AUDIO_VIDEO)
+ kodiFlags |= READ_AUDIO_VIDEO;
+ if (addonFlags & ADDON_READ_AFTER_WRITE)
+ kodiFlags |= READ_AFTER_WRITE;
+ if (addonFlags & READ_REOPEN)
+ kodiFlags |= READ_REOPEN;
+
+ return kodiFlags;
+}
+
+bool Interface_Filesystem::can_open_directory(void* kodiBase, const char* url)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', url='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url));
+ return false;
+ }
+
+ CFileItemList items;
+ return CDirectory::GetDirectory(url, items, "", DIR_FLAG_DEFAULTS | DIR_FLAG_BYPASS_CACHE);
+}
+
+bool Interface_Filesystem::create_directory(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return CDirectory::Create(path);
+}
+
+bool Interface_Filesystem::directory_exists(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return CDirectory::Exists(path, false);
+}
+
+bool Interface_Filesystem::remove_directory(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ // Empty directory
+ CFileItemList fileItems;
+ CDirectory::GetDirectory(path, fileItems, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_BYPASS_CACHE);
+ for (int i = 0; i < fileItems.Size(); ++i)
+ CFile::Delete(fileItems.Get(i)->GetPath());
+
+ return CDirectory::Remove(path);
+}
+
+bool Interface_Filesystem::remove_directory_recursive(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return CDirectory::RemoveRecursive(path);
+}
+
+static void CFileItemListToVFSDirEntries(VFSDirEntry* entries, const CFileItemList& items)
+{
+ for (unsigned int i = 0; i < static_cast<unsigned int>(items.Size()); ++i)
+ {
+ entries[i].label = strdup(items[i]->GetLabel().c_str());
+ entries[i].path = strdup(items[i]->GetPath().c_str());
+ entries[i].size = items[i]->m_dwSize;
+ entries[i].folder = items[i]->m_bIsFolder;
+ items[i]->m_dateTime.GetAsTime(entries[i].date_time);
+ }
+}
+
+bool Interface_Filesystem::get_directory(void* kodiBase,
+ const char* path,
+ const char* mask,
+ struct VFSDirEntry** items,
+ unsigned int* num_items)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr || mask == nullptr || items == nullptr ||
+ num_items == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', path='{}', mask='{}', "
+ "items='{}', num_items='{}'",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path),
+ static_cast<const void*>(mask), static_cast<void*>(items),
+ static_cast<void*>(num_items));
+ return false;
+ }
+
+ CFileItemList fileItems;
+ if (!CDirectory::GetDirectory(path, fileItems, mask,
+ DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_BYPASS_CACHE))
+ return false;
+
+ if (fileItems.Size() > 0)
+ {
+ *num_items = static_cast<unsigned int>(fileItems.Size());
+ *items = new VFSDirEntry[fileItems.Size()];
+ CFileItemListToVFSDirEntries(*items, fileItems);
+ }
+ else
+ {
+ *num_items = 0;
+ *items = nullptr;
+ }
+
+ return true;
+}
+
+void Interface_Filesystem::free_directory(void* kodiBase,
+ struct VFSDirEntry* items,
+ unsigned int num_items)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || items == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', items='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(items));
+ return;
+ }
+
+ for (unsigned int i = 0; i < num_items; ++i)
+ {
+ free(items[i].label);
+ free(items[i].path);
+ }
+ delete[] items;
+}
+
+//------------------------------------------------------------------------------
+
+bool Interface_Filesystem::file_exists(void* kodiBase, const char* filename, bool useCache)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return false;
+ }
+
+ return CFile::Exists(filename, useCache);
+}
+
+bool Interface_Filesystem::stat_file(void* kodiBase,
+ const char* filename,
+ struct STAT_STRUCTURE* buffer)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr || buffer == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}', buffer='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename),
+ static_cast<void*>(buffer));
+ return false;
+ }
+
+ struct __stat64 statBuffer;
+ if (CFile::Stat(filename, &statBuffer) != 0)
+ return false;
+
+ buffer->deviceId = statBuffer.st_dev;
+ buffer->fileSerialNumber = statBuffer.st_ino;
+ buffer->size = statBuffer.st_size;
+ buffer->accessTime = statBuffer.st_atime;
+ buffer->modificationTime = statBuffer.st_mtime;
+ buffer->statusTime = statBuffer.st_ctime;
+ buffer->isDirectory = S_ISDIR(statBuffer.st_mode);
+ buffer->isSymLink = S_ISLNK(statBuffer.st_mode);
+ buffer->isBlock = S_ISBLK(statBuffer.st_mode);
+ buffer->isCharacter = S_ISCHR(statBuffer.st_mode);
+ buffer->isFifo = S_ISFIFO(statBuffer.st_mode);
+ buffer->isRegular = S_ISREG(statBuffer.st_mode);
+ buffer->isSocket = S_ISSOCK(statBuffer.st_mode);
+
+ return true;
+}
+
+bool Interface_Filesystem::delete_file(void* kodiBase, const char* filename)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return false;
+ }
+
+ return CFile::Delete(filename);
+}
+
+bool Interface_Filesystem::rename_file(void* kodiBase,
+ const char* filename,
+ const char* newFileName)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr || newFileName == nullptr)
+ {
+ CLog::Log(
+ LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}', newFileName='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename),
+ static_cast<const void*>(newFileName));
+ return false;
+ }
+
+ return CFile::Rename(filename, newFileName);
+}
+
+bool Interface_Filesystem::copy_file(void* kodiBase, const char* filename, const char* dest)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr || dest == nullptr)
+ {
+ CLog::Log(
+ LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}', dest='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename), static_cast<const void*>(dest));
+ return false;
+ }
+
+ return CFile::Copy(filename, dest);
+}
+
+char* Interface_Filesystem::get_file_md5(void* kodiBase, const char* filename)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return nullptr;
+ }
+
+ std::string string = CUtil::GetFileDigest(filename, KODI::UTILITY::CDigest::Type::MD5);
+ char* buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::get_cache_thumb_name(void* kodiBase, const char* filename)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return nullptr;
+ }
+
+ const auto crc = Crc32::ComputeFromLowerCase(filename);
+ const auto hex = StringUtils::Format("{:08x}.tbn", crc);
+ char* buffer = strdup(hex.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::make_legal_filename(void* kodiBase, const char* filename)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return nullptr;
+ }
+
+ std::string string = CUtil::MakeLegalFileName(filename);
+ char* buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::make_legal_path(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return nullptr;
+ }
+
+ std::string string = CUtil::MakeLegalPath(path);
+ char* buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::translate_special_protocol(void* kodiBase, const char* strSource)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || strSource == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', strSource='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(strSource));
+ return nullptr;
+ }
+
+ return strdup(CSpecialProtocol::TranslatePath(strSource).c_str());
+}
+
+bool Interface_Filesystem::get_disk_space(
+ void* kodiBase, const char* path, uint64_t* capacity, uint64_t* free, uint64_t* available)
+{
+ using namespace KODI::PLATFORM::FILESYSTEM;
+
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr || capacity == nullptr || free == nullptr ||
+ available == nullptr)
+ {
+ CLog::Log(
+ LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', path='{}, capacity='{}, free='{}, "
+ "available='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path), static_cast<void*>(capacity),
+ static_cast<void*>(free), static_cast<void*>(available));
+ return false;
+ }
+
+ std::error_code ec;
+ auto freeSpace = space(CSpecialProtocol::TranslatePath(path), ec);
+ if (ec.value() != 0)
+ return false;
+
+ *capacity = freeSpace.capacity;
+ *free = freeSpace.free;
+ *available = freeSpace.available;
+ return true;
+}
+
+bool Interface_Filesystem::is_internet_stream(void* kodiBase, const char* path, bool strictCheck)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return URIUtils::IsInternetStream(path, strictCheck);
+}
+
+bool Interface_Filesystem::is_on_lan(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return URIUtils::IsOnLAN(path);
+}
+
+bool Interface_Filesystem::is_remote(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return URIUtils::IsRemote(path);
+}
+
+bool Interface_Filesystem::is_local(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return CURL(path).IsLocal();
+}
+
+bool Interface_Filesystem::is_url(void* kodiBase, const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || path == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', path='{})",
+ __FUNCTION__, kodiBase, static_cast<const void*>(path));
+ return false;
+ }
+
+ return URIUtils::IsURL(path);
+}
+
+bool Interface_Filesystem::get_mime_type(void* kodiBase,
+ const char* url,
+ char** content,
+ const char* useragent)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr || content == nullptr || useragent == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', content='{}', "
+ "useragent='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url),
+ static_cast<const void*>(content), static_cast<const void*>(useragent));
+ return false;
+ }
+
+ std::string kodiContent;
+ bool ret = XFILE::CCurlFile::GetMimeType(CURL(url), kodiContent, useragent);
+ if (ret && !kodiContent.empty())
+ {
+ *content = strdup(kodiContent.c_str());
+ }
+ return ret;
+}
+
+bool Interface_Filesystem::get_content_type(void* kodiBase,
+ const char* url,
+ char** content,
+ const char* useragent)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr || content == nullptr || useragent == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', content='{}', "
+ "useragent='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url),
+ static_cast<const void*>(content), static_cast<const void*>(useragent));
+ return false;
+ }
+
+ std::string kodiContent;
+ bool ret = XFILE::CCurlFile::GetContentType(CURL(url), kodiContent, useragent);
+ if (ret && !kodiContent.empty())
+ {
+ *content = strdup(kodiContent.c_str());
+ }
+ return ret;
+}
+
+bool Interface_Filesystem::get_cookies(void* kodiBase, const char* url, char** cookies)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr || cookies == nullptr)
+ {
+ CLog::Log(
+ LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', url='{}', cookies='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url), static_cast<const void*>(cookies));
+ return false;
+ }
+
+ std::string kodiCookies;
+ bool ret = XFILE::CCurlFile::GetCookies(CURL(url), kodiCookies);
+ if (ret && !kodiCookies.empty())
+ {
+ *cookies = strdup(kodiCookies.c_str());
+ }
+ return ret;
+}
+
+bool Interface_Filesystem::get_http_header(void* kodiBase,
+ const char* url,
+ struct KODI_HTTP_HEADER* headers)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr || headers == nullptr || headers->handle == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data pointer given", __func__);
+ return false;
+ }
+
+ CHttpHeader* httpHeader = static_cast<CHttpHeader*>(headers->handle);
+ return XFILE::CCurlFile::GetHttpHeader(CURL(url), *httpHeader);
+}
+
+//------------------------------------------------------------------------------
+
+bool Interface_Filesystem::http_header_create(void* kodiBase, struct KODI_HTTP_HEADER* headers)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || headers == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', headers='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(headers));
+ return false;
+ }
+
+ headers->handle = new CHttpHeader;
+ headers->get_value = http_header_get_value;
+ headers->get_values = http_header_get_values;
+ headers->get_header = http_header_get_header;
+ headers->get_mime_type = http_header_get_mime_type;
+ headers->get_charset = http_header_get_charset;
+ headers->get_proto_line = http_header_get_proto_line;
+
+ return true;
+}
+
+void Interface_Filesystem::http_header_free(void* kodiBase, struct KODI_HTTP_HEADER* headers)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || headers == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', headers='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(headers));
+ return;
+ }
+
+ delete static_cast<CHttpHeader*>(headers->handle);
+ headers->handle = nullptr;
+}
+
+char* Interface_Filesystem::http_header_get_value(void* kodiBase, void* handle, const char* param)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr || param == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}', param='{}')",
+ __FUNCTION__, kodiBase, handle, static_cast<const void*>(param));
+ return nullptr;
+ }
+
+ std::string string = static_cast<CHttpHeader*>(handle)->GetValue(param);
+
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char** Interface_Filesystem::http_header_get_values(void* kodiBase,
+ void* handle,
+ const char* param,
+ int* length)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr || param == nullptr || length == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}', param='{}', "
+ "length='{}')",
+ __FUNCTION__, kodiBase, handle, static_cast<const void*>(param),
+ static_cast<const void*>(length));
+ return nullptr;
+ }
+
+
+ std::vector<std::string> values = static_cast<CHttpHeader*>(handle)->GetValues(param);
+ *length = values.size();
+ char** ret = static_cast<char**>(malloc(sizeof(char*) * values.size()));
+ for (int i = 0; i < *length; ++i)
+ {
+ ret[i] = strdup(values[i].c_str());
+ }
+ return ret;
+}
+
+char* Interface_Filesystem::http_header_get_header(void* kodiBase, void* handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')",
+ __FUNCTION__, kodiBase, handle);
+ return nullptr;
+ }
+
+ std::string string = static_cast<CHttpHeader*>(handle)->GetHeader();
+
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::http_header_get_mime_type(void* kodiBase, void* handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')",
+ __FUNCTION__, kodiBase, handle);
+ return nullptr;
+ }
+
+ std::string string = static_cast<CHttpHeader*>(handle)->GetMimeType();
+
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::http_header_get_charset(void* kodiBase, void* handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')",
+ __FUNCTION__, kodiBase, handle);
+ return nullptr;
+ }
+
+ std::string string = static_cast<CHttpHeader*>(handle)->GetCharset();
+
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Filesystem::http_header_get_proto_line(void* kodiBase, void* handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || handle == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', handle='{}')",
+ __FUNCTION__, kodiBase, handle);
+ return nullptr;
+ }
+
+ std::string string = static_cast<CHttpHeader*>(handle)->GetProtoLine();
+
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+//------------------------------------------------------------------------------
+
+void* Interface_Filesystem::open_file(void* kodiBase, const char* filename, unsigned int flags)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return nullptr;
+ }
+
+ CFile* file = new CFile;
+ if (file->Open(filename, TranslateFileReadBitsToKodi(flags)))
+ return static_cast<void*>(file);
+
+ delete file;
+ return nullptr;
+}
+
+void* Interface_Filesystem::open_file_for_write(void* kodiBase,
+ const char* filename,
+ bool overwrite)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || filename == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', filename='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(filename));
+ return nullptr;
+ }
+
+ CFile* file = new CFile;
+ if (file->OpenForWrite(filename, overwrite))
+ return static_cast<void*>(file);
+
+ delete file;
+ return nullptr;
+}
+
+ssize_t Interface_Filesystem::read_file(void* kodiBase, void* file, void* ptr, size_t size)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || ptr == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}', ptr='{}')",
+ __FUNCTION__, kodiBase, file, ptr);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->Read(ptr, size);
+}
+
+bool Interface_Filesystem::read_file_string(void* kodiBase,
+ void* file,
+ char* szLine,
+ int lineLength)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || szLine == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', file='{}', szLine=='{}')",
+ __FUNCTION__, kodiBase, file, static_cast<void*>(szLine));
+ return false;
+ }
+
+ return static_cast<CFile*>(file)->ReadString(szLine, lineLength);
+}
+
+ssize_t Interface_Filesystem::write_file(void* kodiBase, void* file, const void* ptr, size_t size)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || ptr == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}', ptr='{}')",
+ __FUNCTION__, kodiBase, file, ptr);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->Write(ptr, size);
+}
+
+void Interface_Filesystem::flush_file(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return;
+ }
+
+ static_cast<CFile*>(file)->Flush();
+}
+
+int64_t Interface_Filesystem::seek_file(void* kodiBase, void* file, int64_t position, int whence)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->Seek(position, whence);
+}
+
+int Interface_Filesystem::truncate_file(void* kodiBase, void* file, int64_t size)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->Truncate(size);
+}
+
+int64_t Interface_Filesystem::get_file_position(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->GetPosition();
+}
+
+int64_t Interface_Filesystem::get_file_length(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->GetLength();
+}
+
+double Interface_Filesystem::get_file_download_speed(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return 0.0;
+ }
+
+ return static_cast<CFile*>(file)->GetDownloadSpeed();
+}
+
+void Interface_Filesystem::close_file(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return;
+ }
+
+ static_cast<CFile*>(file)->Close();
+ delete static_cast<CFile*>(file);
+}
+
+int Interface_Filesystem::get_file_chunk_size(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
+ kodiBase, file);
+ return -1;
+ }
+
+ return static_cast<CFile*>(file)->GetChunkSize();
+}
+
+bool Interface_Filesystem::io_control_get_seek_possible(void* kodiBase, void* file)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
+ kodiBase, file);
+ return false;
+ }
+
+ return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_SEEK_POSSIBLE, nullptr) != 0
+ ? true
+ : false;
+}
+
+bool Interface_Filesystem::io_control_get_cache_status(void* kodiBase,
+ void* file,
+ struct VFS_CACHE_STATUS_DATA* status)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || status == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}, status='{}')",
+ __FUNCTION__, kodiBase, file, static_cast<const void*>(status));
+ return false;
+ }
+
+ SCacheStatus data = {};
+ int ret = static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_CACHE_STATUS, &data);
+ if (ret >= 0)
+ {
+ status->forward = data.forward;
+ status->maxrate = data.maxrate;
+ status->currate = data.currate;
+ status->lowrate = data.lowrate;
+ return true;
+ }
+ return false;
+}
+
+bool Interface_Filesystem::io_control_set_cache_rate(void* kodiBase, void* file, uint32_t rate)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
+ kodiBase, file);
+ return false;
+ }
+
+ return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_CACHE_SETRATE, &rate) >= 0 ? true
+ : false;
+}
+
+bool Interface_Filesystem::io_control_set_retry(void* kodiBase, void* file, bool retry)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
+ kodiBase, file);
+ return false;
+ }
+
+ return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_SET_RETRY, &retry) >= 0 ? true
+ : false;
+}
+
+char** Interface_Filesystem::get_property_values(
+ void* kodiBase, void* file, int type, const char* name, int* numValues)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || name == nullptr || numValues == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', file='{}', name='{}', "
+ "numValues='{}')",
+ __FUNCTION__, kodiBase, file, static_cast<const void*>(name),
+ static_cast<void*>(numValues));
+ return nullptr;
+ }
+
+ XFILE::FileProperty internalType;
+ switch (type)
+ {
+ case ADDON_FILE_PROPERTY_RESPONSE_PROTOCOL:
+ internalType = XFILE::FILE_PROPERTY_RESPONSE_PROTOCOL;
+ break;
+ case ADDON_FILE_PROPERTY_RESPONSE_HEADER:
+ internalType = XFILE::FILE_PROPERTY_RESPONSE_HEADER;
+ break;
+ case ADDON_FILE_PROPERTY_CONTENT_TYPE:
+ internalType = XFILE::FILE_PROPERTY_CONTENT_TYPE;
+ break;
+ case ADDON_FILE_PROPERTY_CONTENT_CHARSET:
+ internalType = XFILE::FILE_PROPERTY_CONTENT_CHARSET;
+ break;
+ case ADDON_FILE_PROPERTY_MIME_TYPE:
+ internalType = XFILE::FILE_PROPERTY_MIME_TYPE;
+ break;
+ case ADDON_FILE_PROPERTY_EFFECTIVE_URL:
+ internalType = XFILE::FILE_PROPERTY_EFFECTIVE_URL;
+ break;
+ default:
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return nullptr;
+ };
+ std::vector<std::string> values =
+ static_cast<CFile*>(file)->GetPropertyValues(internalType, name);
+ *numValues = values.size();
+ char** ret = static_cast<char**>(malloc(sizeof(char*) * values.size()));
+ for (int i = 0; i < *numValues; ++i)
+ {
+ ret[i] = strdup(values[i].c_str());
+ }
+ return ret;
+}
+
+void* Interface_Filesystem::curl_create(void* kodiBase, const char* url)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', url='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url));
+ return nullptr;
+ }
+
+ CFile* file = new CFile;
+ if (file->CURLCreate(url))
+ return static_cast<void*>(file);
+
+ delete file;
+ return nullptr;
+}
+
+bool Interface_Filesystem::curl_add_option(
+ void* kodiBase, void* file, int type, const char* name, const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr || name == nullptr || value == nullptr)
+ {
+ CLog::Log(
+ LOGERROR,
+ "Interface_Filesystem::{} - invalid data (addon='{}', file='{}', name='{}', value='{}')",
+ __FUNCTION__, kodiBase, file, static_cast<const void*>(name),
+ static_cast<const void*>(value));
+ return false;
+ }
+
+ XFILE::CURLOPTIONTYPE internalType;
+ switch (type)
+ {
+ case ADDON_CURL_OPTION_OPTION:
+ internalType = XFILE::CURL_OPTION_OPTION;
+ break;
+ case ADDON_CURL_OPTION_PROTOCOL:
+ internalType = XFILE::CURL_OPTION_PROTOCOL;
+ break;
+ case ADDON_CURL_OPTION_CREDENTIALS:
+ internalType = XFILE::CURL_OPTION_CREDENTIALS;
+ break;
+ case ADDON_CURL_OPTION_HEADER:
+ internalType = XFILE::CURL_OPTION_HEADER;
+ break;
+ default:
+ throw std::logic_error("Interface_Filesystem::curl_add_option - invalid curl option type");
+ return false;
+ };
+
+ return static_cast<CFile*>(file)->CURLAddOption(internalType, name, value);
+}
+
+bool Interface_Filesystem::curl_open(void* kodiBase, void* file, unsigned int flags)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || file == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Filesystem::{} - invalid data (addon='{}', file='{}')",
+ __FUNCTION__, kodiBase, file);
+ return false;
+ }
+
+ return static_cast<CFile*>(file)->CURLOpen(TranslateFileReadBitsToKodi(flags));
+}
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/Filesystem.h b/xbmc/addons/interfaces/Filesystem.h
new file mode 100644
index 0000000..55e90ce
--- /dev/null
+++ b/xbmc/addons/interfaces/Filesystem.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/Filesystem.h"
+
+extern "C"
+{
+
+struct VFSDirEntry;
+struct AddonGlobalInterface;
+
+namespace ADDON
+{
+
+struct Interface_Filesystem
+{
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ static unsigned int TranslateFileReadBitsToKodi(unsigned int addonFlags);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note For add of new functions use the "_" style to identify direct a
+ * add-on callback function. Everything with CamelCase is only for the
+ * usage in Kodi only.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ ///@{
+ static bool can_open_directory(void* kodiBase, const char* url);
+ static bool create_directory(void* kodiBase, const char* path);
+ static bool directory_exists(void* kodiBase, const char* path);
+ static bool remove_directory(void* kodiBase, const char* path);
+ static bool remove_directory_recursive(void* kodiBase, const char* path);
+ static bool get_directory(void* kodiBase,
+ const char* path,
+ const char* mask,
+ struct VFSDirEntry** items,
+ unsigned int* num_items);
+ static void free_directory(void* kodiBase, struct VFSDirEntry* items, unsigned int num_items);
+
+ static bool file_exists(void* kodiBase, const char* filename, bool useCache);
+ static bool stat_file(void* kodiBase, const char* filename, struct STAT_STRUCTURE* buffer);
+ static bool delete_file(void* kodiBase, const char* filename);
+ static bool rename_file(void* kodiBase, const char* filename, const char* newFileName);
+ static bool copy_file(void* kodiBase, const char* filename, const char* dest);
+ static char* get_file_md5(void* kodiBase, const char* filename);
+ static char* get_cache_thumb_name(void* kodiBase, const char* filename);
+ static char* make_legal_filename(void* kodiBase, const char* filename);
+ static char* make_legal_path(void* kodiBase, const char* path);
+ static char* translate_special_protocol(void* kodiBase, const char* strSource);
+ static bool get_disk_space(
+ void* kodiBase, const char* path, uint64_t* capacity, uint64_t* free, uint64_t* available);
+ static bool is_internet_stream(void* kodiBase, const char* path, bool strictCheck);
+ static bool is_on_lan(void* kodiBase, const char* path);
+ static bool is_remote(void* kodiBase, const char* path);
+ static bool is_local(void* kodiBase, const char* path);
+ static bool is_url(void* kodiBase, const char* path);
+
+ static bool get_http_header(void* kodiBase, const char* url, struct KODI_HTTP_HEADER* headers);
+ static bool get_mime_type(void* kodiBase, const char* url, char** content, const char* useragent);
+ static bool get_content_type(void* kodiBase,
+ const char* url,
+ char** content,
+ const char* useragent);
+ static bool get_cookies(void* kodiBase, const char* url, char** cookies);
+
+ /*!
+ * @brief Callback functions addon class kodi::vfs::CFile
+ */
+ ///@{
+ static bool http_header_create(void* kodiBase, struct KODI_HTTP_HEADER* headers);
+ static void http_header_free(void* kodiBase, struct KODI_HTTP_HEADER* headers);
+
+ static char* http_header_get_value(void* kodiBase, void* handle, const char* param);
+ static char** http_header_get_values(void* kodiBase,
+ void* handle,
+ const char* param,
+ int* length);
+ static char* http_header_get_header(void* kodiBase, void* handle);
+ static char* http_header_get_mime_type(void* kodiBase, void* handle);
+ static char* http_header_get_charset(void* kodiBase, void* handle);
+ static char* http_header_get_proto_line(void* kodiBase, void* handle);
+ ///@}
+
+ /*!
+ * @brief Callback functions addon class kodi::vfs::CFile
+ */
+ ///@{
+ static void* open_file(void* kodiBase, const char* filename, unsigned int flags);
+ static void* open_file_for_write(void* kodiBase, const char* filename, bool overwrite);
+ static ssize_t read_file(void* kodiBase, void* file, void* ptr, size_t size);
+ static bool read_file_string(void* kodiBase, void* file, char* szLine, int lineLength);
+ static ssize_t write_file(void* kodiBase, void* file, const void* ptr, size_t size);
+ static void flush_file(void* kodiBase, void* file);
+ static int64_t seek_file(void* kodiBase, void* file, int64_t position, int whence);
+ static int truncate_file(void* kodiBase, void* file, int64_t size);
+ static int64_t get_file_position(void* kodiBase, void* file);
+ static int64_t get_file_length(void* kodiBase, void* file);
+ static double get_file_download_speed(void* kodiBase, void* file);
+ static void close_file(void* kodiBase, void* file);
+ static int get_file_chunk_size(void* kodiBase, void* file);
+ static bool io_control_get_seek_possible(void* kodiBase, void* file);
+ static bool io_control_get_cache_status(void* kodiBase,
+ void* file,
+ struct VFS_CACHE_STATUS_DATA* status);
+ static bool io_control_set_cache_rate(void* kodiBase, void* file, uint32_t rate);
+ static bool io_control_set_retry(void* kodiBase, void* file, bool retry);
+ static char** get_property_values(
+ void* kodiBase, void* file, int type, const char* name, int* numValues);
+
+ static void* curl_create(void* kodiBase, const char* url);
+ static bool curl_add_option(
+ void* kodiBase, void* file, int type, const char* name, const char* value);
+ static bool curl_open(void* kodiBase, void* file, unsigned int flags);
+ ///@}
+ ///@}
+};
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/General.cpp b/xbmc/addons/interfaces/General.cpp
new file mode 100644
index 0000000..eef6ccd
--- /dev/null
+++ b/xbmc/addons/interfaces/General.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "General.h"
+
+#include "CompileInfo.h"
+#include "LangInfo.h"
+#include "ServiceBroker.h"
+#include "addons/AddonManager.h"
+#include "addons/AddonVersion.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/General.h"
+#include "application/ApplicationComponents.h"
+#include "application/ApplicationPowerHandling.h"
+#include "dialogs/GUIDialogKaiToast.h"
+#include "input/KeyboardLayout.h"
+#include "input/KeyboardLayoutManager.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "utils/CharsetConverter.h"
+#include "utils/Digest.h"
+#include "utils/LangCodeExpander.h"
+#include "utils/MemUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+#include <string.h>
+
+using namespace kodi; // addon-dev-kit namespace
+using KODI::UTILITY::CDigest;
+
+namespace ADDON
+{
+
+void Interface_General::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi = static_cast<AddonToKodiFuncTable_kodi*>(malloc(sizeof(AddonToKodiFuncTable_kodi)));
+
+ addonInterface->toKodi->kodi->unknown_to_utf8 = unknown_to_utf8;
+ addonInterface->toKodi->kodi->get_language = get_language;
+ addonInterface->toKodi->kodi->queue_notification = queue_notification;
+ addonInterface->toKodi->kodi->get_md5 = get_md5;
+ addonInterface->toKodi->kodi->get_region = get_region;
+ addonInterface->toKodi->kodi->get_free_mem = get_free_mem;
+ addonInterface->toKodi->kodi->get_global_idle_time = get_global_idle_time;
+ addonInterface->toKodi->kodi->is_addon_avilable = is_addon_avilable;
+ addonInterface->toKodi->kodi->kodi_version = kodi_version;
+ addonInterface->toKodi->kodi->get_current_skin_id = get_current_skin_id;
+ addonInterface->toKodi->kodi->get_keyboard_layout = get_keyboard_layout;
+ addonInterface->toKodi->kodi->change_keyboard_layout = change_keyboard_layout;
+}
+
+void Interface_General::DeInit(AddonGlobalInterface* addonInterface)
+{
+ if (addonInterface->toKodi && /* <-- needed as long as the old addon way is used */
+ addonInterface->toKodi->kodi)
+ {
+ free(addonInterface->toKodi->kodi);
+ addonInterface->toKodi->kodi = nullptr;
+ }
+}
+
+char* Interface_General::unknown_to_utf8(void* kodiBase, const char* source, bool* ret, bool failOnBadChar)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon || !source || !ret)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', source='{}', ret='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(source), static_cast<void*>(ret));
+ return nullptr;
+ }
+
+ std::string string;
+ *ret = g_charsetConverter.unknownToUTF8(source, string, failOnBadChar);
+ char* buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_General::get_language(void* kodiBase, int format, bool region)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return nullptr;
+ }
+
+ std::string string = g_langInfo.GetEnglishLanguageName();
+ switch (format)
+ {
+ case LANG_FMT_ISO_639_1:
+ {
+ std::string langCode;
+ g_LangCodeExpander.ConvertToISO6391(string, langCode);
+ string = langCode;
+ if (region)
+ {
+ std::string region2Code;
+ g_LangCodeExpander.ConvertToISO6391(g_langInfo.GetRegionLocale(), region2Code);
+ if (!region2Code.empty())
+ string += "-" + region2Code;
+ }
+ break;
+ }
+ case LANG_FMT_ISO_639_2:
+ {
+ std::string langCode;
+ g_LangCodeExpander.ConvertToISO6392B(string, langCode);
+ string = langCode;
+ if (region)
+ {
+ std::string region3Code;
+ g_LangCodeExpander.ConvertToISO6392B(g_langInfo.GetRegionLocale(), region3Code);
+ if (!region3Code.empty())
+ string += "-" + region3Code;
+ }
+ break;
+ }
+ case LANG_FMT_ENGLISH_NAME:
+ default:
+ {
+ if (region)
+ string += "-" + g_langInfo.GetCurrentRegion();
+ break;
+ }
+ }
+
+ char* buffer = strdup(string.c_str());
+ return buffer;
+}
+
+bool Interface_General::queue_notification(void* kodiBase, int type, const char* header,
+ const char* message, const char* imageFile,
+ unsigned int displayTime, bool withSound,
+ unsigned int messageTime)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || message == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', message='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(message));
+ return false;
+ }
+
+ std::string usedHeader;
+ if (header && strlen(header) > 0)
+ usedHeader = header;
+ else
+ usedHeader = addon->Name();
+
+ QueueMsg qtype = static_cast<QueueMsg>(type);
+
+ if (qtype != QUEUE_OWN_STYLE)
+ {
+ CGUIDialogKaiToast::eMessageType usedType;
+ switch (qtype)
+ {
+ case QueueMsg::QUEUE_WARNING:
+ usedType = CGUIDialogKaiToast::Warning;
+ withSound = true;
+ CLog::Log(LOGDEBUG, "Interface_General::{} - {} - Warning Message: '{}'", __FUNCTION__,
+ addon->Name(), message);
+ break;
+ case QueueMsg::QUEUE_ERROR:
+ usedType = CGUIDialogKaiToast::Error;
+ withSound = true;
+ CLog::Log(LOGDEBUG, "Interface_General::{} - {} - Error Message : '{}'", __FUNCTION__,
+ addon->Name(), message);
+ break;
+ case QueueMsg::QUEUE_INFO:
+ default:
+ usedType = CGUIDialogKaiToast::Info;
+ withSound = false;
+ CLog::Log(LOGDEBUG, "Interface_General::{} - {} - Info Message : '{}'", __FUNCTION__,
+ addon->Name(), message);
+ break;
+ }
+
+ if (imageFile && strlen(imageFile) > 0)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_General::{} - To use given image file '{}' must be type value set to "
+ "'QUEUE_OWN_STYLE'",
+ __FUNCTION__, imageFile);
+ }
+
+ CGUIDialogKaiToast::QueueNotification(usedType, usedHeader, message, 3000, withSound);
+ }
+ else
+ {
+ CGUIDialogKaiToast::QueueNotification(imageFile, usedHeader, message, displayTime, withSound, messageTime);
+ }
+ return true;
+}
+
+void Interface_General::get_md5(void* kodiBase, const char* text, char* md5)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || text == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', text='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(text));
+ return;
+ }
+
+ std::string md5Int = CDigest::Calculate(CDigest::Type::MD5, std::string(text));
+ strncpy(md5, md5Int.c_str(), 40);
+}
+
+char* Interface_General::get_region(void* kodiBase, const char* id)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || id == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', id='{}')", __FUNCTION__,
+ kodiBase, static_cast<const void*>(id));
+ return nullptr;
+ }
+
+ std::string result;
+ if (StringUtils::CompareNoCase(id, "datelong") == 0)
+ {
+ result = g_langInfo.GetDateFormat(true);
+ StringUtils::Replace(result, "DDDD", "%A");
+ StringUtils::Replace(result, "MMMM", "%B");
+ StringUtils::Replace(result, "D", "%d");
+ StringUtils::Replace(result, "YYYY", "%Y");
+ }
+ else if (StringUtils::CompareNoCase(id, "dateshort") == 0)
+ {
+ result = g_langInfo.GetDateFormat(false);
+ StringUtils::Replace(result, "MM", "%m");
+ StringUtils::Replace(result, "DD", "%d");
+#ifdef TARGET_WINDOWS
+ StringUtils::Replace(result, "M", "%#m");
+ StringUtils::Replace(result, "D", "%#d");
+#else
+ StringUtils::Replace(result, "M", "%-m");
+ StringUtils::Replace(result, "D", "%-d");
+#endif
+ StringUtils::Replace(result, "YYYY", "%Y");
+ }
+ else if (StringUtils::CompareNoCase(id, "tempunit") == 0)
+ result = g_langInfo.GetTemperatureUnitString();
+ else if (StringUtils::CompareNoCase(id, "speedunit") == 0)
+ result = g_langInfo.GetSpeedUnitString();
+ else if (StringUtils::CompareNoCase(id, "time") == 0)
+ {
+ result = g_langInfo.GetTimeFormat();
+ StringUtils::Replace(result, "H", "%H");
+ StringUtils::Replace(result, "h", "%I");
+ StringUtils::Replace(result, "mm", "%M");
+ StringUtils::Replace(result, "ss", "%S");
+ StringUtils::Replace(result, "xx", "%p");
+ }
+ else if (StringUtils::CompareNoCase(id, "meridiem") == 0)
+ result = StringUtils::Format("{}/{}", g_langInfo.GetMeridiemSymbol(MeridiemSymbolAM),
+ g_langInfo.GetMeridiemSymbol(MeridiemSymbolPM));
+ else
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - add-on '{}' requests invalid id '{}'",
+ __FUNCTION__, addon->Name(), id);
+ return nullptr;
+ }
+
+ char* buffer = strdup(result.c_str());
+ return buffer;
+}
+
+void Interface_General::get_free_mem(void* kodiBase, long* free, long* total, bool as_bytes)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || free == nullptr || total == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', free='{}', total='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(free), static_cast<void*>(total));
+ return;
+ }
+
+ KODI::MEMORY::MemoryStatus stat;
+ KODI::MEMORY::GetMemoryStatus(&stat);
+ *free = static_cast<long>(stat.availPhys);
+ *total = static_cast<long>(stat.totalPhys);
+ if (!as_bytes)
+ {
+ *free = *free / ( 1024 * 1024 );
+ *total = *total / ( 1024 * 1024 );
+ }
+}
+
+int Interface_General::get_global_idle_time(void* kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return -1;
+ }
+
+ auto& components = CServiceBroker::GetAppComponents();
+ const auto appPower = components.GetComponent<CApplicationPowerHandling>();
+ return appPower->GlobalIdleTime();
+}
+
+bool Interface_General::is_addon_avilable(void* kodiBase,
+ const char* id,
+ char** version,
+ bool* enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || id == nullptr || version == nullptr || enabled == nullptr)
+ {
+ CLog::Log(
+ LOGERROR,
+ "Interface_General::{} - invalid data (addon='{}', id='{}', version='{}', enabled='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(id), static_cast<void*>(version),
+ static_cast<void*>(enabled));
+ return false;
+ }
+
+ AddonPtr addonInfo;
+ if (!CServiceBroker::GetAddonMgr().GetAddon(id, addonInfo, OnlyEnabled::CHOICE_NO))
+ return false;
+
+ *version = strdup(addonInfo->Version().asString().c_str());
+ *enabled = !CServiceBroker::GetAddonMgr().IsAddonDisabled(id);
+ return true;
+}
+
+void Interface_General::kodi_version(void* kodiBase, char** compile_name, int* major, int* minor, char** revision, char** tag, char** tagversion)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || compile_name == nullptr || major == nullptr || minor == nullptr ||
+ revision == nullptr || tag == nullptr || tagversion == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_General::{} - invalid data (addon='{}', compile_name='{}', major='{}', "
+ "minor='{}', revision='{}', tag='{}', tagversion='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(compile_name), static_cast<void*>(major),
+ static_cast<void*>(minor), static_cast<void*>(revision), static_cast<void*>(tag),
+ static_cast<void*>(tagversion));
+ return;
+ }
+
+ *compile_name = strdup(CCompileInfo::GetAppName());
+ *major = CCompileInfo::GetMajor();
+ *minor = CCompileInfo::GetMinor();
+ *revision = strdup(CCompileInfo::GetSCMID());
+ std::string tagStr = CCompileInfo::GetSuffix();
+ if (StringUtils::StartsWithNoCase(tagStr, "alpha"))
+ {
+ *tag = strdup("alpha");
+ *tagversion = strdup(StringUtils::Mid(tagStr, 5).c_str());
+ }
+ else if (StringUtils::StartsWithNoCase(tagStr, "beta"))
+ {
+ *tag = strdup("beta");
+ *tagversion = strdup(StringUtils::Mid(tagStr, 4).c_str());
+ }
+ else if (StringUtils::StartsWithNoCase(tagStr, "rc"))
+ {
+ *tag = strdup("releasecandidate");
+ *tagversion = strdup(StringUtils::Mid(tagStr, 2).c_str());
+ }
+ else if (tagStr.empty())
+ *tag = strdup("stable");
+ else
+ *tag = strdup("prealpha");
+}
+
+char* Interface_General::get_current_skin_id(void* kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return nullptr;
+ }
+
+ return strdup(CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOOKANDFEEL_SKIN).c_str());
+}
+
+bool Interface_General::get_keyboard_layout(void* kodiBase, char** layout_name, int modifier_key, AddonKeyboardKeyTable* c_layout)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || c_layout == nullptr || layout_name == nullptr)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_General::{} - invalid data (addon='{}', c_layout='{}', layout_name='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(c_layout),
+ static_cast<void*>(layout_name));
+ return false;
+ }
+
+ std::string activeLayout = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT);
+
+ CKeyboardLayout layout;
+ if (!CServiceBroker::GetKeyboardLayoutManager()->GetLayout(activeLayout, layout))
+ return false;
+
+ *layout_name = strdup(layout.GetName().c_str());
+
+ unsigned int modifiers = CKeyboardLayout::ModifierKeyNone;
+ if (modifier_key & STD_KB_MODIFIER_KEY_SHIFT)
+ modifiers |= CKeyboardLayout::ModifierKeyShift;
+ if (modifier_key & STD_KB_MODIFIER_KEY_SYMBOL)
+ modifiers |= CKeyboardLayout::ModifierKeySymbol;
+
+ for (unsigned int row = 0; row < STD_KB_BUTTONS_MAX_ROWS; row++)
+ {
+ for (unsigned int column = 0; column < STD_KB_BUTTONS_PER_ROW; column++)
+ {
+ std::string label = layout.GetCharAt(row, column, modifiers);
+ c_layout->keys[row][column] = strdup(label.c_str());
+ }
+ }
+
+ return true;
+}
+
+bool Interface_General::change_keyboard_layout(void* kodiBase, char** layout_name)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || layout_name == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_General::{} - invalid data (addon='{}', layout_name='{}')",
+ __FUNCTION__, kodiBase, static_cast<void*>(layout_name));
+ return false;
+ }
+
+ std::vector<CKeyboardLayout> layouts;
+ unsigned int currentLayout = 0;
+
+ const KeyboardLayouts& keyboardLayouts = CServiceBroker::GetKeyboardLayoutManager()->GetLayouts();
+ const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+ std::vector<CVariant> layoutNames = settings->GetList(CSettings::SETTING_LOCALE_KEYBOARDLAYOUTS);
+ std::string activeLayout = settings->GetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT);
+
+ for (const auto& layoutName : layoutNames)
+ {
+ const auto keyboardLayout = keyboardLayouts.find(layoutName.asString());
+ if (keyboardLayout != keyboardLayouts.end())
+ {
+ layouts.emplace_back(keyboardLayout->second);
+ if (layoutName.asString() == activeLayout)
+ currentLayout = layouts.size() - 1;
+ }
+ }
+
+ currentLayout++;
+ if (currentLayout >= layouts.size())
+ currentLayout = 0;
+ CKeyboardLayout layout = layouts.empty() ? CKeyboardLayout() : layouts[currentLayout];
+ CServiceBroker::GetSettingsComponent()->GetSettings()->SetString(CSettings::SETTING_LOCALE_ACTIVEKEYBOARDLAYOUT, layout.GetName());
+
+ *layout_name = strdup(layout.GetName().c_str());
+ return true;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/General.h b/xbmc/addons/interfaces/General.h
new file mode 100644
index 0000000..6dde356
--- /dev/null
+++ b/xbmc/addons/interfaces/General.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+extern "C"
+{
+
+struct AddonGlobalInterface;
+struct AddonKeyboardKeyTable;
+
+namespace ADDON
+{
+
+/*!
+ * @brief Global general Add-on to Kodi callback functions
+ *
+ * To hold general functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/General.h"
+ */
+struct Interface_General
+{
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static char* unknown_to_utf8(void* kodiBase, const char* source, bool* ret, bool failOnBadChar);
+ static char* get_language(void* kodiBase, int format, bool region);
+ static bool queue_notification(void* kodiBase,
+ int type,
+ const char* header,
+ const char* message,
+ const char* imageFile,
+ unsigned int displayTime,
+ bool withSound,
+ unsigned int messageTime);
+ static void get_md5(void* kodiBase, const char* text, char* md5);
+ static char* get_region(void* kodiBase, const char* id);
+ static void get_free_mem(void* kodiInstance, long* free, long* total, bool as_bytes);
+ static int get_global_idle_time(void* kodiBase);
+ static bool is_addon_avilable(void* kodiBase, const char* id, char** version, bool* enabled);
+ static void kodi_version(void* kodiBase,
+ char** compile_name,
+ int* major,
+ int* minor,
+ char** revision,
+ char** tag,
+ char** tagversion);
+ static char* get_current_skin_id(void* kodiBase);
+ static bool change_keyboard_layout(void* kodiBase, char** layout_name);
+ static bool get_keyboard_layout(void* kodiBase,
+ char** layout_name,
+ int modifier_key,
+ AddonKeyboardKeyTable* c_layout);
+ //@}
+};
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/Network.cpp b/xbmc/addons/interfaces/Network.cpp
new file mode 100644
index 0000000..63151f3
--- /dev/null
+++ b/xbmc/addons/interfaces/Network.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Network.h"
+
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/Network.h"
+#include "network/DNSNameCache.h"
+#include "network/Network.h"
+#include "utils/SystemInfo.h"
+#include "utils/URIUtils.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_Network::Init(AddonGlobalInterface *addonInterface)
+{
+ addonInterface->toKodi->kodi_network = new AddonToKodiFuncTable_kodi_network();
+
+ addonInterface->toKodi->kodi_network->wake_on_lan = wake_on_lan;
+ addonInterface->toKodi->kodi_network->get_ip_address = get_ip_address;
+ addonInterface->toKodi->kodi_network->get_hostname = get_hostname;
+ addonInterface->toKodi->kodi_network->get_user_agent = get_user_agent;
+ addonInterface->toKodi->kodi_network->is_local_host = is_local_host;
+ addonInterface->toKodi->kodi_network->is_host_on_lan = is_host_on_lan;
+ addonInterface->toKodi->kodi_network->dns_lookup = dns_lookup;
+ addonInterface->toKodi->kodi_network->url_encode = url_encode;
+}
+
+void Interface_Network::DeInit(AddonGlobalInterface* addonInterface)
+{
+ if (addonInterface->toKodi) /* <-- needed as long as the old addon way is used */
+ {
+ delete addonInterface->toKodi->kodi_network;
+ addonInterface->toKodi->kodi_network = nullptr;
+ }
+}
+
+bool Interface_Network::wake_on_lan(void* kodiBase, const char* mac)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || mac == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}', mac='{}')", __FUNCTION__,
+ kodiBase, static_cast<const void*>(mac));
+ return false;
+ }
+
+ return CServiceBroker::GetNetwork().WakeOnLan(mac);
+}
+
+char* Interface_Network::get_ip_address(void* kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return nullptr;
+ }
+
+ std::string titleIP;
+ CNetworkInterface* iface = CServiceBroker::GetNetwork().GetFirstConnectedInterface();
+ if (iface)
+ titleIP = iface->GetCurrentIPAddress();
+ else
+ titleIP = "127.0.0.1";
+
+ char* buffer = nullptr;
+ if (!titleIP.empty())
+ buffer = strdup(titleIP.c_str());
+ return buffer;
+}
+
+char* Interface_Network::get_hostname(void* kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return nullptr;
+ }
+
+ std::string hostname;
+ if (!CServiceBroker::GetNetwork().GetHostName(hostname))
+ return nullptr;
+
+ char* buffer = nullptr;
+ if (!hostname.empty())
+ buffer = strdup(hostname.c_str());
+ return buffer;
+}
+
+char* Interface_Network::get_user_agent(void* kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}')", __FUNCTION__,
+ kodiBase);
+ return nullptr;
+ }
+
+ std::string string = CSysInfo::GetUserAgent();
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+bool Interface_Network::is_local_host(void* kodiBase, const char* hostname)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || hostname == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}', hostname='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(hostname));
+ return false;
+ }
+
+ return CServiceBroker::GetNetwork().IsLocalHost(hostname);
+}
+
+bool Interface_Network::is_host_on_lan(void* kodiBase, const char* hostname, bool offLineCheck)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || hostname == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}', hostname='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(hostname));
+ return false;
+ }
+
+ return URIUtils::IsHostOnLAN(hostname, offLineCheck);
+}
+
+char* Interface_Network::dns_lookup(void* kodiBase, const char* url, bool* ret)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr || ret == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}', url='{}', ret='{}')",
+ __FUNCTION__, kodiBase, static_cast<const void*>(url), static_cast<void*>(ret));
+ return nullptr;
+ }
+
+ std::string string;
+ *ret = CDNSNameCache::Lookup(url, string);
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+char* Interface_Network::url_encode(void* kodiBase, const char* url)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (addon == nullptr || url == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_Network::{} - invalid data (addon='{}', url='{}')", __FUNCTION__,
+ kodiBase, static_cast<const void*>(url));
+ return nullptr;
+ }
+
+ std::string string = CURL::Encode(url);
+ char* buffer = nullptr;
+ if (!string.empty())
+ buffer = strdup(string.c_str());
+ return buffer;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/Network.h b/xbmc/addons/interfaces/Network.h
new file mode 100644
index 0000000..b704fb1
--- /dev/null
+++ b/xbmc/addons/interfaces/Network.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+struct AddonGlobalInterface;
+
+extern "C"
+{
+namespace ADDON
+{
+
+/*!
+ * @brief Global general Add-on to Kodi callback functions
+ *
+ * To hold network functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/Network.h"
+ */
+struct Interface_Network
+{
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static bool wake_on_lan(void* kodiBase, const char* mac);
+ static char* get_ip_address(void* kodiBase);
+ static char* get_hostname(void* kodiBase);
+ static char* get_user_agent(void* kodiBase);
+ static bool is_local_host(void* kodiBase, const char* hostname);
+ static bool is_host_on_lan(void* kodiBase, const char* hostname, bool offLineCheck);
+ static char* dns_lookup(void* kodiBase, const char* url, bool* ret);
+ static char* url_encode(void* kodiBase, const char* url);
+ //@}
+};
+
+} /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/CMakeLists.txt b/xbmc/addons/interfaces/gui/CMakeLists.txt
new file mode 100644
index 0000000..3508b82
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(SOURCES GUITranslator.cpp
+ General.cpp
+ ListItem.cpp
+ Window.cpp)
+
+set(HEADERS GUITranslator.h
+ General.h
+ ListItem.h
+ Window.h)
+
+core_add_library(addons_interfaces_gui)
diff --git a/xbmc/addons/interfaces/gui/GUITranslator.cpp b/xbmc/addons/interfaces/gui/GUITranslator.cpp
new file mode 100644
index 0000000..2db2601
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/GUITranslator.cpp
@@ -0,0 +1,969 @@
+/*
+ * Copyright (C) 2005-2020 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GUITranslator.h"
+
+#include "input/actions/ActionIDs.h"
+
+using namespace ADDON;
+
+ADDON_ACTION CAddonGUITranslator::TranslateActionIdToAddon(int kodiId)
+{
+ switch (kodiId)
+ {
+ case ACTION_NONE:
+ return ADDON_ACTION_NONE;
+ case ACTION_MOVE_LEFT:
+ return ADDON_ACTION_MOVE_LEFT;
+ case ACTION_MOVE_RIGHT:
+ return ADDON_ACTION_MOVE_RIGHT;
+ case ACTION_MOVE_UP:
+ return ADDON_ACTION_MOVE_UP;
+ case ACTION_MOVE_DOWN:
+ return ADDON_ACTION_MOVE_DOWN;
+ case ACTION_PAGE_UP:
+ return ADDON_ACTION_PAGE_UP;
+ case ACTION_PAGE_DOWN:
+ return ADDON_ACTION_PAGE_DOWN;
+ case ACTION_SELECT_ITEM:
+ return ADDON_ACTION_SELECT_ITEM;
+ case ACTION_HIGHLIGHT_ITEM:
+ return ADDON_ACTION_HIGHLIGHT_ITEM;
+ case ACTION_PARENT_DIR:
+ return ADDON_ACTION_PARENT_DIR;
+ case ACTION_PREVIOUS_MENU:
+ return ADDON_ACTION_PREVIOUS_MENU;
+ case ACTION_SHOW_INFO:
+ return ADDON_ACTION_SHOW_INFO;
+ case ACTION_PAUSE:
+ return ADDON_ACTION_PAUSE;
+ case ACTION_STOP:
+ return ADDON_ACTION_STOP;
+ case ACTION_NEXT_ITEM:
+ return ADDON_ACTION_NEXT_ITEM;
+ case ACTION_PREV_ITEM:
+ return ADDON_ACTION_PREV_ITEM;
+ case ACTION_FORWARD:
+ return ADDON_ACTION_FORWARD;
+ case ACTION_REWIND:
+ return ADDON_ACTION_REWIND;
+ case ACTION_SHOW_GUI:
+ return ADDON_ACTION_SHOW_GUI;
+ case ACTION_ASPECT_RATIO:
+ return ADDON_ACTION_ASPECT_RATIO;
+ case ACTION_STEP_FORWARD:
+ return ADDON_ACTION_STEP_FORWARD;
+ case ACTION_STEP_BACK:
+ return ADDON_ACTION_STEP_BACK;
+ case ACTION_BIG_STEP_FORWARD:
+ return ADDON_ACTION_BIG_STEP_FORWARD;
+ case ACTION_BIG_STEP_BACK:
+ return ADDON_ACTION_BIG_STEP_BACK;
+ case ACTION_SHOW_OSD:
+ return ADDON_ACTION_SHOW_OSD;
+ case ACTION_SHOW_SUBTITLES:
+ return ADDON_ACTION_SHOW_SUBTITLES;
+ case ACTION_NEXT_SUBTITLE:
+ return ADDON_ACTION_NEXT_SUBTITLE;
+ case ACTION_PLAYER_DEBUG:
+ return ADDON_ACTION_PLAYER_DEBUG;
+ case ACTION_NEXT_PICTURE:
+ return ADDON_ACTION_NEXT_PICTURE;
+ case ACTION_PREV_PICTURE:
+ return ADDON_ACTION_PREV_PICTURE;
+ case ACTION_ZOOM_OUT:
+ return ADDON_ACTION_ZOOM_OUT;
+ case ACTION_ZOOM_IN:
+ return ADDON_ACTION_ZOOM_IN;
+ case ACTION_TOGGLE_SOURCE_DEST:
+ return ADDON_ACTION_TOGGLE_SOURCE_DEST;
+ case ACTION_SHOW_PLAYLIST:
+ return ADDON_ACTION_SHOW_PLAYLIST;
+ case ACTION_QUEUE_ITEM:
+ return ADDON_ACTION_QUEUE_ITEM;
+ case ACTION_REMOVE_ITEM:
+ return ADDON_ACTION_REMOVE_ITEM;
+ case ACTION_SHOW_FULLSCREEN:
+ return ADDON_ACTION_SHOW_FULLSCREEN;
+ case ACTION_ZOOM_LEVEL_NORMAL:
+ return ADDON_ACTION_ZOOM_LEVEL_NORMAL;
+ case ACTION_ZOOM_LEVEL_1:
+ return ADDON_ACTION_ZOOM_LEVEL_1;
+ case ACTION_ZOOM_LEVEL_2:
+ return ADDON_ACTION_ZOOM_LEVEL_2;
+ case ACTION_ZOOM_LEVEL_3:
+ return ADDON_ACTION_ZOOM_LEVEL_3;
+ case ACTION_ZOOM_LEVEL_4:
+ return ADDON_ACTION_ZOOM_LEVEL_4;
+ case ACTION_ZOOM_LEVEL_5:
+ return ADDON_ACTION_ZOOM_LEVEL_5;
+ case ACTION_ZOOM_LEVEL_6:
+ return ADDON_ACTION_ZOOM_LEVEL_6;
+ case ACTION_ZOOM_LEVEL_7:
+ return ADDON_ACTION_ZOOM_LEVEL_7;
+ case ACTION_ZOOM_LEVEL_8:
+ return ADDON_ACTION_ZOOM_LEVEL_8;
+ case ACTION_ZOOM_LEVEL_9:
+ return ADDON_ACTION_ZOOM_LEVEL_9;
+ case ACTION_CALIBRATE_SWAP_ARROWS:
+ return ADDON_ACTION_CALIBRATE_SWAP_ARROWS;
+ case ACTION_CALIBRATE_RESET:
+ return ADDON_ACTION_CALIBRATE_RESET;
+ case ACTION_ANALOG_MOVE:
+ return ADDON_ACTION_ANALOG_MOVE;
+ case ACTION_ROTATE_PICTURE_CW:
+ return ADDON_ACTION_ROTATE_PICTURE_CW;
+ case ACTION_ROTATE_PICTURE_CCW:
+ return ADDON_ACTION_ROTATE_PICTURE_CCW;
+ case ACTION_SUBTITLE_DELAY_MIN:
+ return ADDON_ACTION_SUBTITLE_DELAY_MIN;
+ case ACTION_SUBTITLE_DELAY_PLUS:
+ return ADDON_ACTION_SUBTITLE_DELAY_PLUS;
+ case ACTION_AUDIO_DELAY_MIN:
+ return ADDON_ACTION_AUDIO_DELAY_MIN;
+ case ACTION_AUDIO_DELAY_PLUS:
+ return ADDON_ACTION_AUDIO_DELAY_PLUS;
+ case ACTION_AUDIO_NEXT_LANGUAGE:
+ return ADDON_ACTION_AUDIO_NEXT_LANGUAGE;
+ case ACTION_CHANGE_RESOLUTION:
+ return ADDON_ACTION_CHANGE_RESOLUTION;
+ case REMOTE_0:
+ return ADDON_ACTION_REMOTE_0;
+ case REMOTE_1:
+ return ADDON_ACTION_REMOTE_1;
+ case REMOTE_2:
+ return ADDON_ACTION_REMOTE_2;
+ case REMOTE_3:
+ return ADDON_ACTION_REMOTE_3;
+ case REMOTE_4:
+ return ADDON_ACTION_REMOTE_4;
+ case REMOTE_5:
+ return ADDON_ACTION_REMOTE_5;
+ case REMOTE_6:
+ return ADDON_ACTION_REMOTE_6;
+ case REMOTE_7:
+ return ADDON_ACTION_REMOTE_7;
+ case REMOTE_8:
+ return ADDON_ACTION_REMOTE_8;
+ case REMOTE_9:
+ return ADDON_ACTION_REMOTE_9;
+ case ACTION_PLAYER_PROCESS_INFO:
+ return ADDON_ACTION_PLAYER_PROCESS_INFO;
+ case ACTION_PLAYER_PROGRAM_SELECT:
+ return ADDON_ACTION_PLAYER_PROGRAM_SELECT;
+ case ACTION_PLAYER_RESOLUTION_SELECT:
+ return ADDON_ACTION_PLAYER_RESOLUTION_SELECT;
+ case ACTION_SMALL_STEP_BACK:
+ return ADDON_ACTION_SMALL_STEP_BACK;
+ case ACTION_PLAYER_FORWARD:
+ return ADDON_ACTION_PLAYER_FORWARD;
+ case ACTION_PLAYER_REWIND:
+ return ADDON_ACTION_PLAYER_REWIND;
+ case ACTION_PLAYER_PLAY:
+ return ADDON_ACTION_PLAYER_PLAY;
+ case ACTION_DELETE_ITEM:
+ return ADDON_ACTION_DELETE_ITEM;
+ case ACTION_COPY_ITEM:
+ return ADDON_ACTION_COPY_ITEM;
+ case ACTION_MOVE_ITEM:
+ return ADDON_ACTION_MOVE_ITEM;
+ case ACTION_TAKE_SCREENSHOT:
+ return ADDON_ACTION_TAKE_SCREENSHOT;
+ case ACTION_RENAME_ITEM:
+ return ADDON_ACTION_RENAME_ITEM;
+ case ACTION_VOLUME_UP:
+ return ADDON_ACTION_VOLUME_UP;
+ case ACTION_VOLUME_DOWN:
+ return ADDON_ACTION_VOLUME_DOWN;
+ case ACTION_VOLAMP:
+ return ADDON_ACTION_VOLAMP;
+ case ACTION_MUTE:
+ return ADDON_ACTION_MUTE;
+ case ACTION_NAV_BACK:
+ return ADDON_ACTION_NAV_BACK;
+ case ACTION_VOLAMP_UP:
+ return ADDON_ACTION_VOLAMP_UP;
+ case ACTION_VOLAMP_DOWN:
+ return ADDON_ACTION_VOLAMP_DOWN;
+ case ACTION_CREATE_EPISODE_BOOKMARK:
+ return ADDON_ACTION_CREATE_EPISODE_BOOKMARK;
+ case ACTION_CREATE_BOOKMARK:
+ return ADDON_ACTION_CREATE_BOOKMARK;
+ case ACTION_CHAPTER_OR_BIG_STEP_FORWARD:
+ return ADDON_ACTION_CHAPTER_OR_BIG_STEP_FORWARD;
+ case ACTION_CHAPTER_OR_BIG_STEP_BACK:
+ return ADDON_ACTION_CHAPTER_OR_BIG_STEP_BACK;
+ case ACTION_CYCLE_SUBTITLE:
+ return ADDON_ACTION_CYCLE_SUBTITLE;
+ case ACTION_MOUSE_LEFT_CLICK:
+ return ADDON_ACTION_MOUSE_LEFT_CLICK;
+ case ACTION_MOUSE_RIGHT_CLICK:
+ return ADDON_ACTION_MOUSE_RIGHT_CLICK;
+ case ACTION_MOUSE_MIDDLE_CLICK:
+ return ADDON_ACTION_MOUSE_MIDDLE_CLICK;
+ case ACTION_MOUSE_DOUBLE_CLICK:
+ return ADDON_ACTION_MOUSE_DOUBLE_CLICK;
+ case ACTION_MOUSE_WHEEL_UP:
+ return ADDON_ACTION_MOUSE_WHEEL_UP;
+ case ACTION_MOUSE_WHEEL_DOWN:
+ return ADDON_ACTION_MOUSE_WHEEL_DOWN;
+ case ACTION_MOUSE_DRAG:
+ return ADDON_ACTION_MOUSE_DRAG;
+ case ACTION_MOUSE_MOVE:
+ return ADDON_ACTION_MOUSE_MOVE;
+ case ACTION_MOUSE_LONG_CLICK:
+ return ADDON_ACTION_MOUSE_LONG_CLICK;
+ case ACTION_MOUSE_DRAG_END:
+ return ADDON_ACTION_MOUSE_DRAG_END;
+ case ACTION_BACKSPACE:
+ return ADDON_ACTION_BACKSPACE;
+ case ACTION_SCROLL_UP:
+ return ADDON_ACTION_SCROLL_UP;
+ case ACTION_SCROLL_DOWN:
+ return ADDON_ACTION_SCROLL_DOWN;
+ case ACTION_ANALOG_FORWARD:
+ return ADDON_ACTION_ANALOG_FORWARD;
+ case ACTION_ANALOG_REWIND:
+ return ADDON_ACTION_ANALOG_REWIND;
+ case ACTION_MOVE_ITEM_UP:
+ return ADDON_ACTION_MOVE_ITEM_UP;
+ case ACTION_MOVE_ITEM_DOWN:
+ return ADDON_ACTION_MOVE_ITEM_DOWN;
+ case ACTION_CONTEXT_MENU:
+ return ADDON_ACTION_CONTEXT_MENU;
+ case ACTION_SHIFT:
+ return ADDON_ACTION_SHIFT;
+ case ACTION_SYMBOLS:
+ return ADDON_ACTION_SYMBOLS;
+ case ACTION_CURSOR_LEFT:
+ return ADDON_ACTION_CURSOR_LEFT;
+ case ACTION_CURSOR_RIGHT:
+ return ADDON_ACTION_CURSOR_RIGHT;
+ case ACTION_BUILT_IN_FUNCTION:
+ return ADDON_ACTION_BUILT_IN_FUNCTION;
+ case ACTION_SHOW_OSD_TIME:
+ return ADDON_ACTION_SHOW_OSD_TIME;
+ case ACTION_ANALOG_SEEK_FORWARD:
+ return ADDON_ACTION_ANALOG_SEEK_FORWARD;
+ case ACTION_ANALOG_SEEK_BACK:
+ return ADDON_ACTION_ANALOG_SEEK_BACK;
+ case ACTION_VIS_PRESET_SHOW:
+ return ADDON_ACTION_VIS_PRESET_SHOW;
+ case ACTION_VIS_PRESET_NEXT:
+ return ADDON_ACTION_VIS_PRESET_NEXT;
+ case ACTION_VIS_PRESET_PREV:
+ return ADDON_ACTION_VIS_PRESET_PREV;
+ case ACTION_VIS_PRESET_LOCK:
+ return ADDON_ACTION_VIS_PRESET_LOCK;
+ case ACTION_VIS_PRESET_RANDOM:
+ return ADDON_ACTION_VIS_PRESET_RANDOM;
+ case ACTION_VIS_RATE_PRESET_PLUS:
+ return ADDON_ACTION_VIS_RATE_PRESET_PLUS;
+ case ACTION_VIS_RATE_PRESET_MINUS:
+ return ADDON_ACTION_VIS_RATE_PRESET_MINUS;
+ case ACTION_SHOW_VIDEOMENU:
+ return ADDON_ACTION_SHOW_VIDEOMENU;
+ case ACTION_ENTER:
+ return ADDON_ACTION_ENTER;
+ case ACTION_INCREASE_RATING:
+ return ADDON_ACTION_INCREASE_RATING;
+ case ACTION_DECREASE_RATING:
+ return ADDON_ACTION_DECREASE_RATING;
+ case ACTION_NEXT_SCENE:
+ return ADDON_ACTION_NEXT_SCENE;
+ case ACTION_PREV_SCENE:
+ return ADDON_ACTION_PREV_SCENE;
+ case ACTION_NEXT_LETTER:
+ return ADDON_ACTION_NEXT_LETTER;
+ case ACTION_PREV_LETTER:
+ return ADDON_ACTION_PREV_LETTER;
+ case ACTION_JUMP_SMS2:
+ return ADDON_ACTION_JUMP_SMS2;
+ case ACTION_JUMP_SMS3:
+ return ADDON_ACTION_JUMP_SMS3;
+ case ACTION_JUMP_SMS4:
+ return ADDON_ACTION_JUMP_SMS4;
+ case ACTION_JUMP_SMS5:
+ return ADDON_ACTION_JUMP_SMS5;
+ case ACTION_JUMP_SMS6:
+ return ADDON_ACTION_JUMP_SMS6;
+ case ACTION_JUMP_SMS7:
+ return ADDON_ACTION_JUMP_SMS7;
+ case ACTION_JUMP_SMS8:
+ return ADDON_ACTION_JUMP_SMS8;
+ case ACTION_JUMP_SMS9:
+ return ADDON_ACTION_JUMP_SMS9;
+ case ACTION_FILTER_CLEAR:
+ return ADDON_ACTION_FILTER_CLEAR;
+ case ACTION_FILTER_SMS2:
+ return ADDON_ACTION_FILTER_SMS2;
+ case ACTION_FILTER_SMS3:
+ return ADDON_ACTION_FILTER_SMS3;
+ case ACTION_FILTER_SMS4:
+ return ADDON_ACTION_FILTER_SMS4;
+ case ACTION_FILTER_SMS5:
+ return ADDON_ACTION_FILTER_SMS5;
+ case ACTION_FILTER_SMS6:
+ return ADDON_ACTION_FILTER_SMS6;
+ case ACTION_FILTER_SMS7:
+ return ADDON_ACTION_FILTER_SMS7;
+ case ACTION_FILTER_SMS8:
+ return ADDON_ACTION_FILTER_SMS8;
+ case ACTION_FILTER_SMS9:
+ return ADDON_ACTION_FILTER_SMS9;
+ case ACTION_FIRST_PAGE:
+ return ADDON_ACTION_FIRST_PAGE;
+ case ACTION_LAST_PAGE:
+ return ADDON_ACTION_LAST_PAGE;
+ case ACTION_AUDIO_DELAY:
+ return ADDON_ACTION_AUDIO_DELAY;
+ case ACTION_SUBTITLE_DELAY:
+ return ADDON_ACTION_SUBTITLE_DELAY;
+ case ACTION_MENU:
+ return ADDON_ACTION_MENU;
+ case ACTION_SET_RATING:
+ return ADDON_ACTION_SET_RATING;
+ case ACTION_RECORD:
+ return ADDON_ACTION_RECORD;
+ case ACTION_PASTE:
+ return ADDON_ACTION_PASTE;
+ case ACTION_NEXT_CONTROL:
+ return ADDON_ACTION_NEXT_CONTROL;
+ case ACTION_PREV_CONTROL:
+ return ADDON_ACTION_PREV_CONTROL;
+ case ACTION_CHANNEL_SWITCH:
+ return ADDON_ACTION_CHANNEL_SWITCH;
+ case ACTION_CHANNEL_UP:
+ return ADDON_ACTION_CHANNEL_UP;
+ case ACTION_CHANNEL_DOWN:
+ return ADDON_ACTION_CHANNEL_DOWN;
+ case ACTION_NEXT_CHANNELGROUP:
+ return ADDON_ACTION_NEXT_CHANNELGROUP;
+ case ACTION_PREVIOUS_CHANNELGROUP:
+ return ADDON_ACTION_PREVIOUS_CHANNELGROUP;
+ case ACTION_PVR_PLAY:
+ return ADDON_ACTION_PVR_PLAY;
+ case ACTION_PVR_PLAY_TV:
+ return ADDON_ACTION_PVR_PLAY_TV;
+ case ACTION_PVR_PLAY_RADIO:
+ return ADDON_ACTION_PVR_PLAY_RADIO;
+ case ACTION_PVR_SHOW_TIMER_RULE:
+ return ADDON_ACTION_PVR_SHOW_TIMER_RULE;
+ case ACTION_CHANNEL_NUMBER_SEP:
+ return ADDON_ACTION_CHANNEL_NUMBER_SEP;
+ case ACTION_PVR_ANNOUNCE_REMINDERS:
+ return ADDON_ACTION_PVR_ANNOUNCE_REMINDERS;
+ case ACTION_TOGGLE_FULLSCREEN:
+ return ADDON_ACTION_TOGGLE_FULLSCREEN;
+ case ACTION_TOGGLE_WATCHED:
+ return ADDON_ACTION_TOGGLE_WATCHED;
+ case ACTION_SCAN_ITEM:
+ return ADDON_ACTION_SCAN_ITEM;
+ case ACTION_TOGGLE_DIGITAL_ANALOG:
+ return ADDON_ACTION_TOGGLE_DIGITAL_ANALOG;
+ case ACTION_RELOAD_KEYMAPS:
+ return ADDON_ACTION_RELOAD_KEYMAPS;
+ case ACTION_GUIPROFILE_BEGIN:
+ return ADDON_ACTION_GUIPROFILE_BEGIN;
+ case ACTION_TELETEXT_RED:
+ return ADDON_ACTION_TELETEXT_RED;
+ case ACTION_TELETEXT_GREEN:
+ return ADDON_ACTION_TELETEXT_GREEN;
+ case ACTION_TELETEXT_YELLOW:
+ return ADDON_ACTION_TELETEXT_YELLOW;
+ case ACTION_TELETEXT_BLUE:
+ return ADDON_ACTION_TELETEXT_BLUE;
+ case ACTION_INCREASE_PAR:
+ return ADDON_ACTION_INCREASE_PAR;
+ case ACTION_DECREASE_PAR:
+ return ADDON_ACTION_DECREASE_PAR;
+ case ACTION_VSHIFT_UP:
+ return ADDON_ACTION_VSHIFT_UP;
+ case ACTION_VSHIFT_DOWN:
+ return ADDON_ACTION_VSHIFT_DOWN;
+ case ACTION_PLAYER_PLAYPAUSE:
+ return ADDON_ACTION_PLAYER_PLAYPAUSE;
+ case ACTION_SUBTITLE_VSHIFT_UP:
+ return ADDON_ACTION_SUBTITLE_VSHIFT_UP;
+ case ACTION_SUBTITLE_VSHIFT_DOWN:
+ return ADDON_ACTION_SUBTITLE_VSHIFT_DOWN;
+ case ACTION_SUBTITLE_ALIGN:
+ return ADDON_ACTION_SUBTITLE_ALIGN;
+ case ACTION_FILTER:
+ return ADDON_ACTION_FILTER;
+ case ACTION_SWITCH_PLAYER:
+ return ADDON_ACTION_SWITCH_PLAYER;
+ case ACTION_STEREOMODE_NEXT:
+ return ADDON_ACTION_STEREOMODE_NEXT;
+ case ACTION_STEREOMODE_PREVIOUS:
+ return ADDON_ACTION_STEREOMODE_PREVIOUS;
+ case ACTION_STEREOMODE_TOGGLE:
+ return ADDON_ACTION_STEREOMODE_TOGGLE;
+ case ACTION_STEREOMODE_SELECT:
+ return ADDON_ACTION_STEREOMODE_SELECT;
+ case ACTION_STEREOMODE_TOMONO:
+ return ADDON_ACTION_STEREOMODE_TOMONO;
+ case ACTION_STEREOMODE_SET:
+ return ADDON_ACTION_STEREOMODE_SET;
+ case ACTION_SETTINGS_RESET:
+ return ADDON_ACTION_SETTINGS_RESET;
+ case ACTION_SETTINGS_LEVEL_CHANGE:
+ return ADDON_ACTION_SETTINGS_LEVEL_CHANGE;
+ case ACTION_TRIGGER_OSD:
+ return ADDON_ACTION_TRIGGER_OSD;
+ case ACTION_INPUT_TEXT:
+ return ADDON_ACTION_INPUT_TEXT;
+ case ACTION_VOLUME_SET:
+ return ADDON_ACTION_VOLUME_SET;
+ case ACTION_TOGGLE_COMMSKIP:
+ return ADDON_ACTION_TOGGLE_COMMSKIP;
+ case ACTION_BROWSE_SUBTITLE:
+ return ADDON_ACTION_BROWSE_SUBTITLE;
+ case ACTION_PLAYER_RESET:
+ return ADDON_ACTION_PLAYER_RESET;
+ case ACTION_TOGGLE_FONT:
+ return ADDON_ACTION_TOGGLE_FONT;
+ case ACTION_VIDEO_NEXT_STREAM:
+ return ADDON_ACTION_VIDEO_NEXT_STREAM;
+ case ACTION_QUEUE_ITEM_NEXT:
+ return ADDON_ACTION_QUEUE_ITEM_NEXT;
+ case ACTION_HDR_TOGGLE:
+ return ADDON_ACTION_HDR_TOGGLE;
+ case ACTION_VOICE_RECOGNIZE:
+ return ADDON_ACTION_VOICE_RECOGNIZE;
+ case ACTION_TOUCH_TAP:
+ return ADDON_ACTION_TOUCH_TAP;
+ case ACTION_TOUCH_TAP_TEN:
+ return ADDON_ACTION_TOUCH_TAP_TEN;
+ case ACTION_TOUCH_LONGPRESS:
+ return ADDON_ACTION_TOUCH_LONGPRESS;
+ case ACTION_TOUCH_LONGPRESS_TEN:
+ return ADDON_ACTION_TOUCH_LONGPRESS_TEN;
+ case ACTION_GESTURE_NOTIFY:
+ return ADDON_ACTION_GESTURE_NOTIFY;
+ case ACTION_GESTURE_BEGIN:
+ return ADDON_ACTION_GESTURE_BEGIN;
+ case ACTION_GESTURE_ZOOM:
+ return ADDON_ACTION_GESTURE_ZOOM;
+ case ACTION_GESTURE_ROTATE:
+ return ADDON_ACTION_GESTURE_ROTATE;
+ case ACTION_GESTURE_PAN:
+ return ADDON_ACTION_GESTURE_PAN;
+ case ACTION_GESTURE_ABORT:
+ return ADDON_ACTION_GESTURE_ABORT;
+ case ACTION_GESTURE_SWIPE_LEFT:
+ return ADDON_ACTION_GESTURE_SWIPE_LEFT;
+ case ACTION_GESTURE_SWIPE_LEFT_TEN:
+ return ADDON_ACTION_GESTURE_SWIPE_LEFT_TEN;
+ case ACTION_GESTURE_SWIPE_RIGHT:
+ return ADDON_ACTION_GESTURE_SWIPE_RIGHT;
+ case ACTION_GESTURE_SWIPE_RIGHT_TEN:
+ return ADDON_ACTION_GESTURE_SWIPE_RIGHT_TEN;
+ case ACTION_GESTURE_SWIPE_UP:
+ return ADDON_ACTION_GESTURE_SWIPE_UP;
+ case ACTION_GESTURE_SWIPE_UP_TEN:
+ return ADDON_ACTION_GESTURE_SWIPE_UP_TEN;
+ case ACTION_GESTURE_SWIPE_DOWN:
+ return ADDON_ACTION_GESTURE_SWIPE_DOWN;
+ case ACTION_GESTURE_SWIPE_DOWN_TEN:
+ return ADDON_ACTION_GESTURE_SWIPE_DOWN_TEN;
+ case ACTION_GESTURE_END:
+ return ADDON_ACTION_GESTURE_END;
+ case ACTION_ANALOG_MOVE_X_LEFT:
+ return ADDON_ACTION_ANALOG_MOVE_X_LEFT;
+ case ACTION_ANALOG_MOVE_X_RIGHT:
+ return ADDON_ACTION_ANALOG_MOVE_X_RIGHT;
+ case ACTION_ANALOG_MOVE_Y_UP:
+ return ADDON_ACTION_ANALOG_MOVE_Y_UP;
+ case ACTION_ANALOG_MOVE_Y_DOWN:
+ return ADDON_ACTION_ANALOG_MOVE_Y_DOWN;
+ case ACTION_ERROR:
+ return ADDON_ACTION_ERROR;
+ case ACTION_NOOP:
+ default:
+ return ADDON_ACTION_NOOP;
+ }
+}
+
+int CAddonGUITranslator::TranslateActionIdToKodi(ADDON_ACTION addonId)
+{
+ switch (addonId)
+ {
+ case ADDON_ACTION_NONE:
+ return ACTION_NONE;
+ case ADDON_ACTION_MOVE_LEFT:
+ return ACTION_MOVE_LEFT;
+ case ADDON_ACTION_MOVE_RIGHT:
+ return ACTION_MOVE_RIGHT;
+ case ADDON_ACTION_MOVE_UP:
+ return ACTION_MOVE_UP;
+ case ADDON_ACTION_MOVE_DOWN:
+ return ACTION_MOVE_DOWN;
+ case ADDON_ACTION_PAGE_UP:
+ return ACTION_PAGE_UP;
+ case ADDON_ACTION_PAGE_DOWN:
+ return ACTION_PAGE_DOWN;
+ case ADDON_ACTION_SELECT_ITEM:
+ return ACTION_SELECT_ITEM;
+ case ADDON_ACTION_HIGHLIGHT_ITEM:
+ return ACTION_HIGHLIGHT_ITEM;
+ case ADDON_ACTION_PARENT_DIR:
+ return ACTION_PARENT_DIR;
+ case ADDON_ACTION_PREVIOUS_MENU:
+ return ACTION_PREVIOUS_MENU;
+ case ADDON_ACTION_SHOW_INFO:
+ return ACTION_SHOW_INFO;
+ case ADDON_ACTION_PAUSE:
+ return ACTION_PAUSE;
+ case ADDON_ACTION_STOP:
+ return ACTION_STOP;
+ case ADDON_ACTION_NEXT_ITEM:
+ return ACTION_NEXT_ITEM;
+ case ADDON_ACTION_PREV_ITEM:
+ return ACTION_PREV_ITEM;
+ case ADDON_ACTION_FORWARD:
+ return ACTION_FORWARD;
+ case ADDON_ACTION_REWIND:
+ return ACTION_REWIND;
+ case ADDON_ACTION_SHOW_GUI:
+ return ACTION_SHOW_GUI;
+ case ADDON_ACTION_ASPECT_RATIO:
+ return ACTION_ASPECT_RATIO;
+ case ADDON_ACTION_STEP_FORWARD:
+ return ACTION_STEP_FORWARD;
+ case ADDON_ACTION_STEP_BACK:
+ return ACTION_STEP_BACK;
+ case ADDON_ACTION_BIG_STEP_FORWARD:
+ return ACTION_BIG_STEP_FORWARD;
+ case ADDON_ACTION_BIG_STEP_BACK:
+ return ACTION_BIG_STEP_BACK;
+ case ADDON_ACTION_SHOW_OSD:
+ return ACTION_SHOW_OSD;
+ case ADDON_ACTION_SHOW_SUBTITLES:
+ return ACTION_SHOW_SUBTITLES;
+ case ADDON_ACTION_NEXT_SUBTITLE:
+ return ACTION_NEXT_SUBTITLE;
+ case ADDON_ACTION_PLAYER_DEBUG:
+ return ACTION_PLAYER_DEBUG;
+ case ADDON_ACTION_NEXT_PICTURE:
+ return ACTION_NEXT_PICTURE;
+ case ADDON_ACTION_PREV_PICTURE:
+ return ACTION_PREV_PICTURE;
+ case ADDON_ACTION_ZOOM_OUT:
+ return ACTION_ZOOM_OUT;
+ case ADDON_ACTION_ZOOM_IN:
+ return ACTION_ZOOM_IN;
+ case ADDON_ACTION_TOGGLE_SOURCE_DEST:
+ return ACTION_TOGGLE_SOURCE_DEST;
+ case ADDON_ACTION_SHOW_PLAYLIST:
+ return ACTION_SHOW_PLAYLIST;
+ case ADDON_ACTION_QUEUE_ITEM:
+ return ACTION_QUEUE_ITEM;
+ case ADDON_ACTION_REMOVE_ITEM:
+ return ACTION_REMOVE_ITEM;
+ case ADDON_ACTION_SHOW_FULLSCREEN:
+ return ACTION_SHOW_FULLSCREEN;
+ case ADDON_ACTION_ZOOM_LEVEL_NORMAL:
+ return ACTION_ZOOM_LEVEL_NORMAL;
+ case ADDON_ACTION_ZOOM_LEVEL_1:
+ return ACTION_ZOOM_LEVEL_1;
+ case ADDON_ACTION_ZOOM_LEVEL_2:
+ return ACTION_ZOOM_LEVEL_2;
+ case ADDON_ACTION_ZOOM_LEVEL_3:
+ return ACTION_ZOOM_LEVEL_3;
+ case ADDON_ACTION_ZOOM_LEVEL_4:
+ return ACTION_ZOOM_LEVEL_4;
+ case ADDON_ACTION_ZOOM_LEVEL_5:
+ return ACTION_ZOOM_LEVEL_5;
+ case ADDON_ACTION_ZOOM_LEVEL_6:
+ return ACTION_ZOOM_LEVEL_6;
+ case ADDON_ACTION_ZOOM_LEVEL_7:
+ return ACTION_ZOOM_LEVEL_7;
+ case ADDON_ACTION_ZOOM_LEVEL_8:
+ return ACTION_ZOOM_LEVEL_8;
+ case ADDON_ACTION_ZOOM_LEVEL_9:
+ return ACTION_ZOOM_LEVEL_9;
+ case ADDON_ACTION_CALIBRATE_SWAP_ARROWS:
+ return ACTION_CALIBRATE_SWAP_ARROWS;
+ case ADDON_ACTION_CALIBRATE_RESET:
+ return ACTION_CALIBRATE_RESET;
+ case ADDON_ACTION_ANALOG_MOVE:
+ return ACTION_ANALOG_MOVE;
+ case ADDON_ACTION_ROTATE_PICTURE_CW:
+ return ACTION_ROTATE_PICTURE_CW;
+ case ADDON_ACTION_ROTATE_PICTURE_CCW:
+ return ACTION_ROTATE_PICTURE_CCW;
+ case ADDON_ACTION_SUBTITLE_DELAY_MIN:
+ return ACTION_SUBTITLE_DELAY_MIN;
+ case ADDON_ACTION_SUBTITLE_DELAY_PLUS:
+ return ACTION_SUBTITLE_DELAY_PLUS;
+ case ADDON_ACTION_AUDIO_DELAY_MIN:
+ return ACTION_AUDIO_DELAY_MIN;
+ case ADDON_ACTION_AUDIO_DELAY_PLUS:
+ return ACTION_AUDIO_DELAY_PLUS;
+ case ADDON_ACTION_AUDIO_NEXT_LANGUAGE:
+ return ACTION_AUDIO_NEXT_LANGUAGE;
+ case ADDON_ACTION_CHANGE_RESOLUTION:
+ return ACTION_CHANGE_RESOLUTION;
+ case ADDON_ACTION_REMOTE_0:
+ return REMOTE_0;
+ case ADDON_ACTION_REMOTE_1:
+ return REMOTE_1;
+ case ADDON_ACTION_REMOTE_2:
+ return REMOTE_2;
+ case ADDON_ACTION_REMOTE_3:
+ return REMOTE_3;
+ case ADDON_ACTION_REMOTE_4:
+ return REMOTE_4;
+ case ADDON_ACTION_REMOTE_5:
+ return REMOTE_5;
+ case ADDON_ACTION_REMOTE_6:
+ return REMOTE_6;
+ case ADDON_ACTION_REMOTE_7:
+ return REMOTE_7;
+ case ADDON_ACTION_REMOTE_8:
+ return REMOTE_8;
+ case ADDON_ACTION_REMOTE_9:
+ return REMOTE_9;
+ case ADDON_ACTION_PLAYER_PROCESS_INFO:
+ return ACTION_PLAYER_PROCESS_INFO;
+ case ADDON_ACTION_PLAYER_PROGRAM_SELECT:
+ return ACTION_PLAYER_PROGRAM_SELECT;
+ case ADDON_ACTION_PLAYER_RESOLUTION_SELECT:
+ return ACTION_PLAYER_RESOLUTION_SELECT;
+ case ADDON_ACTION_SMALL_STEP_BACK:
+ return ACTION_SMALL_STEP_BACK;
+ case ADDON_ACTION_PLAYER_FORWARD:
+ return ACTION_PLAYER_FORWARD;
+ case ADDON_ACTION_PLAYER_REWIND:
+ return ACTION_PLAYER_REWIND;
+ case ADDON_ACTION_PLAYER_PLAY:
+ return ACTION_PLAYER_PLAY;
+ case ADDON_ACTION_DELETE_ITEM:
+ return ACTION_DELETE_ITEM;
+ case ADDON_ACTION_COPY_ITEM:
+ return ACTION_COPY_ITEM;
+ case ADDON_ACTION_MOVE_ITEM:
+ return ACTION_MOVE_ITEM;
+ case ADDON_ACTION_TAKE_SCREENSHOT:
+ return ACTION_TAKE_SCREENSHOT;
+ case ADDON_ACTION_RENAME_ITEM:
+ return ACTION_RENAME_ITEM;
+ case ADDON_ACTION_VOLUME_UP:
+ return ACTION_VOLUME_UP;
+ case ADDON_ACTION_VOLUME_DOWN:
+ return ACTION_VOLUME_DOWN;
+ case ADDON_ACTION_VOLAMP:
+ return ACTION_VOLAMP;
+ case ADDON_ACTION_MUTE:
+ return ACTION_MUTE;
+ case ADDON_ACTION_NAV_BACK:
+ return ACTION_NAV_BACK;
+ case ADDON_ACTION_VOLAMP_UP:
+ return ACTION_VOLAMP_UP;
+ case ADDON_ACTION_VOLAMP_DOWN:
+ return ACTION_VOLAMP_DOWN;
+ case ADDON_ACTION_CREATE_EPISODE_BOOKMARK:
+ return ACTION_CREATE_EPISODE_BOOKMARK;
+ case ADDON_ACTION_CREATE_BOOKMARK:
+ return ACTION_CREATE_BOOKMARK;
+ case ADDON_ACTION_CHAPTER_OR_BIG_STEP_FORWARD:
+ return ACTION_CHAPTER_OR_BIG_STEP_FORWARD;
+ case ADDON_ACTION_CHAPTER_OR_BIG_STEP_BACK:
+ return ACTION_CHAPTER_OR_BIG_STEP_BACK;
+ case ADDON_ACTION_CYCLE_SUBTITLE:
+ return ACTION_CYCLE_SUBTITLE;
+ case ADDON_ACTION_MOUSE_LEFT_CLICK:
+ return ACTION_MOUSE_LEFT_CLICK;
+ case ADDON_ACTION_MOUSE_RIGHT_CLICK:
+ return ACTION_MOUSE_RIGHT_CLICK;
+ case ADDON_ACTION_MOUSE_MIDDLE_CLICK:
+ return ACTION_MOUSE_MIDDLE_CLICK;
+ case ADDON_ACTION_MOUSE_DOUBLE_CLICK:
+ return ACTION_MOUSE_DOUBLE_CLICK;
+ case ADDON_ACTION_MOUSE_WHEEL_UP:
+ return ACTION_MOUSE_WHEEL_UP;
+ case ADDON_ACTION_MOUSE_WHEEL_DOWN:
+ return ACTION_MOUSE_WHEEL_DOWN;
+ case ADDON_ACTION_MOUSE_DRAG:
+ return ACTION_MOUSE_DRAG;
+ case ADDON_ACTION_MOUSE_MOVE:
+ return ACTION_MOUSE_MOVE;
+ case ADDON_ACTION_MOUSE_LONG_CLICK:
+ return ACTION_MOUSE_LONG_CLICK;
+ case ADDON_ACTION_MOUSE_DRAG_END:
+ return ACTION_MOUSE_DRAG_END;
+ case ADDON_ACTION_BACKSPACE:
+ return ACTION_BACKSPACE;
+ case ADDON_ACTION_SCROLL_UP:
+ return ACTION_SCROLL_UP;
+ case ADDON_ACTION_SCROLL_DOWN:
+ return ACTION_SCROLL_DOWN;
+ case ADDON_ACTION_ANALOG_FORWARD:
+ return ACTION_ANALOG_FORWARD;
+ case ADDON_ACTION_ANALOG_REWIND:
+ return ACTION_ANALOG_REWIND;
+ case ADDON_ACTION_MOVE_ITEM_UP:
+ return ACTION_MOVE_ITEM_UP;
+ case ADDON_ACTION_MOVE_ITEM_DOWN:
+ return ACTION_MOVE_ITEM_DOWN;
+ case ADDON_ACTION_CONTEXT_MENU:
+ return ACTION_CONTEXT_MENU;
+ case ADDON_ACTION_SHIFT:
+ return ACTION_SHIFT;
+ case ADDON_ACTION_SYMBOLS:
+ return ACTION_SYMBOLS;
+ case ADDON_ACTION_CURSOR_LEFT:
+ return ACTION_CURSOR_LEFT;
+ case ADDON_ACTION_CURSOR_RIGHT:
+ return ACTION_CURSOR_RIGHT;
+ case ADDON_ACTION_BUILT_IN_FUNCTION:
+ return ACTION_BUILT_IN_FUNCTION;
+ case ADDON_ACTION_SHOW_OSD_TIME:
+ return ACTION_SHOW_OSD_TIME;
+ case ADDON_ACTION_ANALOG_SEEK_FORWARD:
+ return ACTION_ANALOG_SEEK_FORWARD;
+ case ADDON_ACTION_ANALOG_SEEK_BACK:
+ return ACTION_ANALOG_SEEK_BACK;
+ case ADDON_ACTION_VIS_PRESET_SHOW:
+ return ACTION_VIS_PRESET_SHOW;
+ case ADDON_ACTION_VIS_PRESET_NEXT:
+ return ACTION_VIS_PRESET_NEXT;
+ case ADDON_ACTION_VIS_PRESET_PREV:
+ return ACTION_VIS_PRESET_PREV;
+ case ADDON_ACTION_VIS_PRESET_LOCK:
+ return ACTION_VIS_PRESET_LOCK;
+ case ADDON_ACTION_VIS_PRESET_RANDOM:
+ return ACTION_VIS_PRESET_RANDOM;
+ case ADDON_ACTION_VIS_RATE_PRESET_PLUS:
+ return ACTION_VIS_RATE_PRESET_PLUS;
+ case ADDON_ACTION_VIS_RATE_PRESET_MINUS:
+ return ACTION_VIS_RATE_PRESET_MINUS;
+ case ADDON_ACTION_SHOW_VIDEOMENU:
+ return ACTION_SHOW_VIDEOMENU;
+ case ADDON_ACTION_ENTER:
+ return ACTION_ENTER;
+ case ADDON_ACTION_INCREASE_RATING:
+ return ACTION_INCREASE_RATING;
+ case ADDON_ACTION_DECREASE_RATING:
+ return ACTION_DECREASE_RATING;
+ case ADDON_ACTION_NEXT_SCENE:
+ return ACTION_NEXT_SCENE;
+ case ADDON_ACTION_PREV_SCENE:
+ return ACTION_PREV_SCENE;
+ case ADDON_ACTION_NEXT_LETTER:
+ return ACTION_NEXT_LETTER;
+ case ADDON_ACTION_PREV_LETTER:
+ return ACTION_PREV_LETTER;
+ case ADDON_ACTION_JUMP_SMS2:
+ return ACTION_JUMP_SMS2;
+ case ADDON_ACTION_JUMP_SMS3:
+ return ACTION_JUMP_SMS3;
+ case ADDON_ACTION_JUMP_SMS4:
+ return ACTION_JUMP_SMS4;
+ case ADDON_ACTION_JUMP_SMS5:
+ return ACTION_JUMP_SMS5;
+ case ADDON_ACTION_JUMP_SMS6:
+ return ACTION_JUMP_SMS6;
+ case ADDON_ACTION_JUMP_SMS7:
+ return ACTION_JUMP_SMS7;
+ case ADDON_ACTION_JUMP_SMS8:
+ return ACTION_JUMP_SMS8;
+ case ADDON_ACTION_JUMP_SMS9:
+ return ACTION_JUMP_SMS9;
+ case ADDON_ACTION_FILTER_CLEAR:
+ return ACTION_FILTER_CLEAR;
+ case ADDON_ACTION_FILTER_SMS2:
+ return ACTION_FILTER_SMS2;
+ case ADDON_ACTION_FILTER_SMS3:
+ return ACTION_FILTER_SMS3;
+ case ADDON_ACTION_FILTER_SMS4:
+ return ACTION_FILTER_SMS4;
+ case ADDON_ACTION_FILTER_SMS5:
+ return ACTION_FILTER_SMS5;
+ case ADDON_ACTION_FILTER_SMS6:
+ return ACTION_FILTER_SMS6;
+ case ADDON_ACTION_FILTER_SMS7:
+ return ACTION_FILTER_SMS7;
+ case ADDON_ACTION_FILTER_SMS8:
+ return ACTION_FILTER_SMS8;
+ case ADDON_ACTION_FILTER_SMS9:
+ return ACTION_FILTER_SMS9;
+ case ADDON_ACTION_FIRST_PAGE:
+ return ACTION_FIRST_PAGE;
+ case ADDON_ACTION_LAST_PAGE:
+ return ACTION_LAST_PAGE;
+ case ADDON_ACTION_AUDIO_DELAY:
+ return ACTION_AUDIO_DELAY;
+ case ADDON_ACTION_SUBTITLE_DELAY:
+ return ACTION_SUBTITLE_DELAY;
+ case ADDON_ACTION_MENU:
+ return ACTION_MENU;
+ case ADDON_ACTION_SET_RATING:
+ return ACTION_SET_RATING;
+ case ADDON_ACTION_RECORD:
+ return ACTION_RECORD;
+ case ADDON_ACTION_PASTE:
+ return ACTION_PASTE;
+ case ADDON_ACTION_NEXT_CONTROL:
+ return ACTION_NEXT_CONTROL;
+ case ADDON_ACTION_PREV_CONTROL:
+ return ACTION_PREV_CONTROL;
+ case ADDON_ACTION_CHANNEL_SWITCH:
+ return ACTION_CHANNEL_SWITCH;
+ case ADDON_ACTION_CHANNEL_UP:
+ return ACTION_CHANNEL_UP;
+ case ADDON_ACTION_CHANNEL_DOWN:
+ return ACTION_CHANNEL_DOWN;
+ case ADDON_ACTION_NEXT_CHANNELGROUP:
+ return ACTION_NEXT_CHANNELGROUP;
+ case ADDON_ACTION_PREVIOUS_CHANNELGROUP:
+ return ACTION_PREVIOUS_CHANNELGROUP;
+ case ADDON_ACTION_PVR_PLAY:
+ return ACTION_PVR_PLAY;
+ case ADDON_ACTION_PVR_PLAY_TV:
+ return ACTION_PVR_PLAY_TV;
+ case ADDON_ACTION_PVR_PLAY_RADIO:
+ return ACTION_PVR_PLAY_RADIO;
+ case ADDON_ACTION_PVR_SHOW_TIMER_RULE:
+ return ACTION_PVR_SHOW_TIMER_RULE;
+ case ADDON_ACTION_CHANNEL_NUMBER_SEP:
+ return ACTION_CHANNEL_NUMBER_SEP;
+ case ADDON_ACTION_PVR_ANNOUNCE_REMINDERS:
+ return ACTION_PVR_ANNOUNCE_REMINDERS;
+ case ADDON_ACTION_TOGGLE_FULLSCREEN:
+ return ACTION_TOGGLE_FULLSCREEN;
+ case ADDON_ACTION_TOGGLE_WATCHED:
+ return ACTION_TOGGLE_WATCHED;
+ case ADDON_ACTION_SCAN_ITEM:
+ return ACTION_SCAN_ITEM;
+ case ADDON_ACTION_TOGGLE_DIGITAL_ANALOG:
+ return ACTION_TOGGLE_DIGITAL_ANALOG;
+ case ADDON_ACTION_RELOAD_KEYMAPS:
+ return ACTION_RELOAD_KEYMAPS;
+ case ADDON_ACTION_GUIPROFILE_BEGIN:
+ return ACTION_GUIPROFILE_BEGIN;
+ case ADDON_ACTION_TELETEXT_RED:
+ return ACTION_TELETEXT_RED;
+ case ADDON_ACTION_TELETEXT_GREEN:
+ return ACTION_TELETEXT_GREEN;
+ case ADDON_ACTION_TELETEXT_YELLOW:
+ return ACTION_TELETEXT_YELLOW;
+ case ADDON_ACTION_TELETEXT_BLUE:
+ return ACTION_TELETEXT_BLUE;
+ case ADDON_ACTION_INCREASE_PAR:
+ return ACTION_INCREASE_PAR;
+ case ADDON_ACTION_DECREASE_PAR:
+ return ACTION_DECREASE_PAR;
+ case ADDON_ACTION_VSHIFT_UP:
+ return ACTION_VSHIFT_UP;
+ case ADDON_ACTION_VSHIFT_DOWN:
+ return ACTION_VSHIFT_DOWN;
+ case ADDON_ACTION_PLAYER_PLAYPAUSE:
+ return ACTION_PLAYER_PLAYPAUSE;
+ case ADDON_ACTION_SUBTITLE_VSHIFT_UP:
+ return ACTION_SUBTITLE_VSHIFT_UP;
+ case ADDON_ACTION_SUBTITLE_VSHIFT_DOWN:
+ return ACTION_SUBTITLE_VSHIFT_DOWN;
+ case ADDON_ACTION_SUBTITLE_ALIGN:
+ return ACTION_SUBTITLE_ALIGN;
+ case ADDON_ACTION_FILTER:
+ return ACTION_FILTER;
+ case ADDON_ACTION_SWITCH_PLAYER:
+ return ACTION_SWITCH_PLAYER;
+ case ADDON_ACTION_STEREOMODE_NEXT:
+ return ACTION_STEREOMODE_NEXT;
+ case ADDON_ACTION_STEREOMODE_PREVIOUS:
+ return ACTION_STEREOMODE_PREVIOUS;
+ case ADDON_ACTION_STEREOMODE_TOGGLE:
+ return ACTION_STEREOMODE_TOGGLE;
+ case ADDON_ACTION_STEREOMODE_SELECT:
+ return ACTION_STEREOMODE_SELECT;
+ case ADDON_ACTION_STEREOMODE_TOMONO:
+ return ACTION_STEREOMODE_TOMONO;
+ case ADDON_ACTION_STEREOMODE_SET:
+ return ACTION_STEREOMODE_SET;
+ case ADDON_ACTION_SETTINGS_RESET:
+ return ACTION_SETTINGS_RESET;
+ case ADDON_ACTION_SETTINGS_LEVEL_CHANGE:
+ return ACTION_SETTINGS_LEVEL_CHANGE;
+ case ADDON_ACTION_TRIGGER_OSD:
+ return ACTION_TRIGGER_OSD;
+ case ADDON_ACTION_INPUT_TEXT:
+ return ACTION_INPUT_TEXT;
+ case ADDON_ACTION_VOLUME_SET:
+ return ACTION_VOLUME_SET;
+ case ADDON_ACTION_TOGGLE_COMMSKIP:
+ return ACTION_TOGGLE_COMMSKIP;
+ case ADDON_ACTION_BROWSE_SUBTITLE:
+ return ACTION_BROWSE_SUBTITLE;
+ case ADDON_ACTION_PLAYER_RESET:
+ return ACTION_PLAYER_RESET;
+ case ADDON_ACTION_TOGGLE_FONT:
+ return ACTION_TOGGLE_FONT;
+ case ADDON_ACTION_VIDEO_NEXT_STREAM:
+ return ACTION_VIDEO_NEXT_STREAM;
+ case ADDON_ACTION_QUEUE_ITEM_NEXT:
+ return ACTION_QUEUE_ITEM_NEXT;
+ case ADDON_ACTION_HDR_TOGGLE:
+ return ACTION_HDR_TOGGLE;
+ case ADDON_ACTION_VOICE_RECOGNIZE:
+ return ACTION_VOICE_RECOGNIZE;
+ case ADDON_ACTION_TOUCH_TAP:
+ return ACTION_TOUCH_TAP;
+ case ADDON_ACTION_TOUCH_TAP_TEN:
+ return ACTION_TOUCH_TAP_TEN;
+ case ADDON_ACTION_TOUCH_LONGPRESS:
+ return ACTION_TOUCH_LONGPRESS;
+ case ADDON_ACTION_TOUCH_LONGPRESS_TEN:
+ return ACTION_TOUCH_LONGPRESS_TEN;
+ case ADDON_ACTION_GESTURE_NOTIFY:
+ return ACTION_GESTURE_NOTIFY;
+ case ADDON_ACTION_GESTURE_BEGIN:
+ return ACTION_GESTURE_BEGIN;
+ case ADDON_ACTION_GESTURE_ZOOM:
+ return ACTION_GESTURE_ZOOM;
+ case ADDON_ACTION_GESTURE_ROTATE:
+ return ACTION_GESTURE_ROTATE;
+ case ADDON_ACTION_GESTURE_PAN:
+ return ACTION_GESTURE_PAN;
+ case ADDON_ACTION_GESTURE_ABORT:
+ return ACTION_GESTURE_ABORT;
+ case ADDON_ACTION_GESTURE_SWIPE_LEFT:
+ return ACTION_GESTURE_SWIPE_LEFT;
+ case ADDON_ACTION_GESTURE_SWIPE_LEFT_TEN:
+ return ACTION_GESTURE_SWIPE_LEFT_TEN;
+ case ADDON_ACTION_GESTURE_SWIPE_RIGHT:
+ return ACTION_GESTURE_SWIPE_RIGHT;
+ case ADDON_ACTION_GESTURE_SWIPE_RIGHT_TEN:
+ return ACTION_GESTURE_SWIPE_RIGHT_TEN;
+ case ADDON_ACTION_GESTURE_SWIPE_UP:
+ return ACTION_GESTURE_SWIPE_UP;
+ case ADDON_ACTION_GESTURE_SWIPE_UP_TEN:
+ return ACTION_GESTURE_SWIPE_UP_TEN;
+ case ADDON_ACTION_GESTURE_SWIPE_DOWN:
+ return ACTION_GESTURE_SWIPE_DOWN;
+ case ADDON_ACTION_GESTURE_SWIPE_DOWN_TEN:
+ return ACTION_GESTURE_SWIPE_DOWN_TEN;
+ case ADDON_ACTION_GESTURE_END:
+ return ACTION_GESTURE_END;
+ case ADDON_ACTION_ANALOG_MOVE_X_LEFT:
+ return ACTION_ANALOG_MOVE_X_LEFT;
+ case ADDON_ACTION_ANALOG_MOVE_X_RIGHT:
+ return ACTION_ANALOG_MOVE_X_RIGHT;
+ case ADDON_ACTION_ANALOG_MOVE_Y_UP:
+ return ACTION_ANALOG_MOVE_Y_UP;
+ case ADDON_ACTION_ANALOG_MOVE_Y_DOWN:
+ return ACTION_ANALOG_MOVE_Y_DOWN;
+ case ADDON_ACTION_ERROR:
+ return ACTION_ERROR;
+ case ADDON_ACTION_NOOP:
+ default:
+ return ACTION_NOOP;
+ }
+}
diff --git a/xbmc/addons/interfaces/gui/GUITranslator.h b/xbmc/addons/interfaces/gui/GUITranslator.h
new file mode 100644
index 0000000..8bd6b5c
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/GUITranslator.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005-2020 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/input/action_ids.h"
+
+namespace ADDON
+{
+
+/*!
+ * \brief Translates data types from GUI API to the corresponding format in Kodi.
+ *
+ * This class is stateless.
+ */
+class CAddonGUITranslator
+{
+ CAddonGUITranslator() = delete;
+
+public:
+ /*!
+ * \brief Translate Kodi's action id's to addon
+ * \param kodiId Kodi's action identifier
+ * \return Addon action identifier
+ */
+ static ADDON_ACTION TranslateActionIdToAddon(int kodiId);
+
+ /*!
+ * \brief Translate addon's action id's to Kodi
+ * \param addonId Addon's action identifier
+ * \return Kodi action identifier
+ */
+ static int TranslateActionIdToKodi(ADDON_ACTION addonId);
+};
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/General.cpp b/xbmc/addons/interfaces/gui/General.cpp
new file mode 100644
index 0000000..a0a5583
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/General.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "General.h"
+
+#include "ListItem.h"
+#include "ServiceBroker.h"
+#include "Window.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/General.h"
+#include "controls/Button.h"
+#include "controls/Edit.h"
+#include "controls/FadeLabel.h"
+#include "controls/Image.h"
+#include "controls/Label.h"
+#include "controls/Progress.h"
+#include "controls/RadioButton.h"
+#include "controls/Rendering.h"
+#include "controls/SettingsSlider.h"
+#include "controls/Slider.h"
+#include "controls/Spin.h"
+#include "controls/TextBox.h"
+#include "dialogs/ContextMenu.h"
+#include "dialogs/ExtendedProgressBar.h"
+#include "dialogs/FileBrowser.h"
+#include "dialogs/Keyboard.h"
+#include "dialogs/Numeric.h"
+#include "dialogs/OK.h"
+#include "dialogs/Progress.h"
+#include "dialogs/Select.h"
+#include "dialogs/TextViewer.h"
+#include "dialogs/YesNo.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "utils/log.h"
+
+#include <mutex>
+
+namespace ADDON
+{
+int Interface_GUIGeneral::m_iAddonGUILockRef = 0;
+
+void Interface_GUIGeneral::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui = new AddonToKodiFuncTable_kodi_gui();
+
+ Interface_GUIControlButton::Init(addonInterface);
+ Interface_GUIControlEdit::Init(addonInterface);
+ Interface_GUIControlFadeLabel::Init(addonInterface);
+ Interface_GUIControlImage::Init(addonInterface);
+ Interface_GUIControlLabel::Init(addonInterface);
+ Interface_GUIControlProgress::Init(addonInterface);
+ Interface_GUIControlRadioButton::Init(addonInterface);
+ Interface_GUIControlAddonRendering::Init(addonInterface);
+ Interface_GUIControlSettingsSlider::Init(addonInterface);
+ Interface_GUIControlSlider::Init(addonInterface);
+ Interface_GUIControlSpin::Init(addonInterface);
+ Interface_GUIControlTextBox::Init(addonInterface);
+ Interface_GUIDialogContextMenu::Init(addonInterface);
+ Interface_GUIDialogExtendedProgress::Init(addonInterface);
+ Interface_GUIDialogFileBrowser::Init(addonInterface);
+ Interface_GUIDialogKeyboard::Init(addonInterface);
+ Interface_GUIDialogNumeric::Init(addonInterface);
+ Interface_GUIDialogOK::Init(addonInterface);
+ Interface_GUIDialogProgress::Init(addonInterface);
+ Interface_GUIDialogSelect::Init(addonInterface);
+ Interface_GUIDialogTextViewer::Init(addonInterface);
+ Interface_GUIDialogYesNo::Init(addonInterface);
+ Interface_GUIListItem::Init(addonInterface);
+ Interface_GUIWindow::Init(addonInterface);
+
+ addonInterface->toKodi->kodi_gui->general = new AddonToKodiFuncTable_kodi_gui_general();
+
+ addonInterface->toKodi->kodi_gui->general->lock = lock;
+ addonInterface->toKodi->kodi_gui->general->unlock = unlock;
+ addonInterface->toKodi->kodi_gui->general->get_screen_height = get_screen_height;
+ addonInterface->toKodi->kodi_gui->general->get_screen_width = get_screen_width;
+ addonInterface->toKodi->kodi_gui->general->get_video_resolution = get_video_resolution;
+ addonInterface->toKodi->kodi_gui->general->get_current_window_dialog_id =
+ get_current_window_dialog_id;
+ addonInterface->toKodi->kodi_gui->general->get_current_window_id = get_current_window_id;
+ addonInterface->toKodi->kodi_gui->general->get_hw_context = get_hw_context;
+ addonInterface->toKodi->kodi_gui->general->get_adjust_refresh_rate_status =
+ get_adjust_refresh_rate_status;
+}
+
+void Interface_GUIGeneral::DeInit(AddonGlobalInterface* addonInterface)
+{
+ if (addonInterface->toKodi && /* <-- needed as long as the old addon way is used */
+ addonInterface->toKodi->kodi_gui)
+ {
+ Interface_GUIControlButton::DeInit(addonInterface);
+ Interface_GUIControlEdit::DeInit(addonInterface);
+ Interface_GUIControlFadeLabel::DeInit(addonInterface);
+ Interface_GUIControlImage::DeInit(addonInterface);
+ Interface_GUIControlLabel::DeInit(addonInterface);
+ Interface_GUIControlProgress::DeInit(addonInterface);
+ Interface_GUIControlRadioButton::DeInit(addonInterface);
+ Interface_GUIControlAddonRendering::DeInit(addonInterface);
+ Interface_GUIControlSettingsSlider::DeInit(addonInterface);
+ Interface_GUIControlSlider::DeInit(addonInterface);
+ Interface_GUIControlSpin::DeInit(addonInterface);
+ Interface_GUIControlTextBox::DeInit(addonInterface);
+ Interface_GUIDialogContextMenu::DeInit(addonInterface);
+ Interface_GUIDialogExtendedProgress::DeInit(addonInterface);
+ Interface_GUIDialogFileBrowser::DeInit(addonInterface);
+ Interface_GUIDialogKeyboard::DeInit(addonInterface);
+ Interface_GUIDialogNumeric::DeInit(addonInterface);
+ Interface_GUIDialogOK::DeInit(addonInterface);
+ Interface_GUIDialogProgress::DeInit(addonInterface);
+ Interface_GUIDialogSelect::DeInit(addonInterface);
+ Interface_GUIDialogTextViewer::DeInit(addonInterface);
+ Interface_GUIDialogYesNo::DeInit(addonInterface);
+ Interface_GUIListItem::DeInit(addonInterface);
+ Interface_GUIWindow::DeInit(addonInterface);
+
+ delete addonInterface->toKodi->kodi_gui->general;
+ delete addonInterface->toKodi->kodi_gui;
+ addonInterface->toKodi->kodi_gui = nullptr;
+ }
+}
+
+//@{
+void Interface_GUIGeneral::lock()
+{
+ if (m_iAddonGUILockRef == 0)
+ CServiceBroker::GetWinSystem()->GetGfxContext().lock();
+ ++m_iAddonGUILockRef;
+}
+
+void Interface_GUIGeneral::unlock()
+{
+ if (m_iAddonGUILockRef > 0)
+ {
+ --m_iAddonGUILockRef;
+ if (m_iAddonGUILockRef == 0)
+ CServiceBroker::GetWinSystem()->GetGfxContext().unlock();
+ }
+}
+//@}
+
+//@{
+int Interface_GUIGeneral::get_screen_height(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return -1;
+ }
+
+ return CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight();
+}
+
+int Interface_GUIGeneral::get_screen_width(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return -1;
+ }
+
+ return CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth();
+}
+
+int Interface_GUIGeneral::get_video_resolution(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return -1;
+ }
+
+ return (int)CServiceBroker::GetWinSystem()->GetGfxContext().GetVideoResolution();
+}
+//@}
+
+//@{
+int Interface_GUIGeneral::get_current_window_dialog_id(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return -1;
+ }
+
+ std::unique_lock<CCriticalSection> gl(CServiceBroker::GetWinSystem()->GetGfxContext());
+ return CServiceBroker::GetGUI()->GetWindowManager().GetTopmostModalDialog();
+}
+
+int Interface_GUIGeneral::get_current_window_id(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return -1;
+ }
+
+ std::unique_lock<CCriticalSection> gl(CServiceBroker::GetWinSystem()->GetGfxContext());
+ return CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
+}
+
+ADDON_HARDWARE_CONTEXT Interface_GUIGeneral::get_hw_context(KODI_HANDLE kodiBase)
+{
+ return CServiceBroker::GetWinSystem()->GetHWContext();
+}
+
+AdjustRefreshRateStatus Interface_GUIGeneral::get_adjust_refresh_rate_status(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "kodi::gui::{} - invalid data", __func__);
+ return ADJUST_REFRESHRATE_STATUS_OFF;
+ }
+
+ switch (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
+ CSettings::SETTING_VIDEOPLAYER_ADJUSTREFRESHRATE))
+ {
+ case AdjustRefreshRate::ADJUST_REFRESHRATE_OFF:
+ return ADJUST_REFRESHRATE_STATUS_OFF;
+ break;
+ case AdjustRefreshRate::ADJUST_REFRESHRATE_ON_START:
+ return ADJUST_REFRESHRATE_STATUS_ON_START;
+ break;
+ case AdjustRefreshRate::ADJUST_REFRESHRATE_ON_STARTSTOP:
+ return ADJUST_REFRESHRATE_STATUS_ON_STARTSTOP;
+ break;
+ case AdjustRefreshRate::ADJUST_REFRESHRATE_ALWAYS:
+ return ADJUST_REFRESHRATE_STATUS_ALWAYS;
+ break;
+ default:
+ CLog::Log(LOGERROR, "kodi::gui::{} - Unhandled Adjust refresh rate setting", __func__);
+ return ADJUST_REFRESHRATE_STATUS_OFF;
+ break;
+ }
+}
+
+//@}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/General.h b/xbmc/addons/interfaces/gui/General.h
new file mode 100644
index 0000000..146d4f7
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/General.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/general.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/General.h"
+ */
+ struct Interface_GUIGeneral
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note For add of new functions use the "_" style to identify direct a
+ * add-on callback function. Everything with CamelCase is only for the
+ * usage in Kodi only.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void lock();
+ static void unlock();
+
+ static int get_screen_height(KODI_HANDLE kodiBase);
+ static int get_screen_width(KODI_HANDLE kodiBase);
+ static int get_video_resolution(KODI_HANDLE kodiBase);
+ static int get_current_window_dialog_id(KODI_HANDLE kodiBase);
+ static int get_current_window_id(KODI_HANDLE kodiBase);
+ static ADDON_HARDWARE_CONTEXT get_hw_context(KODI_HANDLE kodiBase);
+ static AdjustRefreshRateStatus get_adjust_refresh_rate_status(KODI_HANDLE kodiBase);
+ //@}
+
+ private:
+ static int m_iAddonGUILockRef;
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/ListItem.cpp b/xbmc/addons/interfaces/gui/ListItem.cpp
new file mode 100644
index 0000000..c91e451
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/ListItem.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "ListItem.h"
+
+#include "FileItem.h"
+#include "General.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/ListItem.h"
+#include "utils/StringUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIListItem::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->listItem = new AddonToKodiFuncTable_kodi_gui_listItem();
+
+ addonInterface->toKodi->kodi_gui->listItem->create = create;
+ addonInterface->toKodi->kodi_gui->listItem->destroy = destroy;
+ addonInterface->toKodi->kodi_gui->listItem->get_label = get_label;
+ addonInterface->toKodi->kodi_gui->listItem->set_label = set_label;
+ addonInterface->toKodi->kodi_gui->listItem->get_label2 = get_label2;
+ addonInterface->toKodi->kodi_gui->listItem->set_label2 = set_label2;
+ addonInterface->toKodi->kodi_gui->listItem->get_art = get_art;
+ addonInterface->toKodi->kodi_gui->listItem->set_art = set_art;
+ addonInterface->toKodi->kodi_gui->listItem->get_path = get_path;
+ addonInterface->toKodi->kodi_gui->listItem->set_path = set_path;
+ addonInterface->toKodi->kodi_gui->listItem->get_property = get_property;
+ addonInterface->toKodi->kodi_gui->listItem->set_property = set_property;
+ addonInterface->toKodi->kodi_gui->listItem->select = select;
+ addonInterface->toKodi->kodi_gui->listItem->is_selected = is_selected;
+}
+
+void Interface_GUIListItem::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->listItem;
+}
+
+KODI_GUI_LISTITEM_HANDLE Interface_GUIListItem::create(KODI_HANDLE kodiBase,
+ const char* label,
+ const char* label2,
+ const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "ADDON::Interface_GUIListItem::{} - invalid data", __func__);
+ return nullptr;
+ }
+
+ CFileItemPtr* item = new CFileItemPtr(new CFileItem());
+ if (label)
+ item->get()->SetLabel(label);
+ if (label2)
+ item->get()->SetLabel2(label2);
+ if (path)
+ item->get()->SetPath(path);
+
+ return item;
+}
+
+void Interface_GUIListItem::destroy(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "ADDON::Interface_GUIListItem::{} - invalid data", __func__);
+ return;
+ }
+
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (item)
+ delete item;
+}
+
+char* Interface_GUIListItem::get_label(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return nullptr;
+ }
+
+ char* ret;
+ Interface_GUIGeneral::lock();
+ ret = strdup(item->get()->GetLabel().c_str());
+ Interface_GUIGeneral::unlock();
+ return ret;
+}
+
+void Interface_GUIListItem::set_label(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ item->get()->SetLabel(label);
+ Interface_GUIGeneral::unlock();
+}
+
+char* Interface_GUIListItem::get_label2(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return nullptr;
+ }
+
+ char* ret;
+ Interface_GUIGeneral::lock();
+ ret = strdup(item->get()->GetLabel2().c_str());
+ Interface_GUIGeneral::unlock();
+ return ret;
+}
+
+void Interface_GUIListItem::set_label2(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ item->get()->SetLabel2(label);
+ Interface_GUIGeneral::unlock();
+}
+
+char* Interface_GUIListItem::get_art(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* type)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !type)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', type='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(type),
+ addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return nullptr;
+ }
+
+ char* ret;
+ Interface_GUIGeneral::lock();
+ ret = strdup(item->get()->GetArt(type).c_str());
+ Interface_GUIGeneral::unlock();
+ return ret;
+}
+
+void Interface_GUIListItem::set_art(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* type,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !type || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}', type= "
+ "'{}', label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(type),
+ static_cast<const void*>(label), addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ item->get()->SetArt(type, label);
+ Interface_GUIGeneral::unlock();
+}
+
+char* Interface_GUIListItem::get_path(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return nullptr;
+ }
+
+ char* ret;
+ Interface_GUIGeneral::lock();
+ ret = strdup(item->get()->GetPath().c_str());
+ Interface_GUIGeneral::unlock();
+ return ret;
+}
+
+
+void Interface_GUIListItem::set_path(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* path)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !path)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', path='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(path),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ item->get()->SetPath(path);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIListItem::set_property(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* key,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !key || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}', value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ static_cast<const void*>(value), addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ item->get()->SetProperty(lowerKey, CVariant(value));
+ Interface_GUIGeneral::unlock();
+}
+
+char* Interface_GUIListItem::get_property(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return nullptr;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ char* ret = strdup(item->get()->GetProperty(lowerKey).asString().c_str());
+ Interface_GUIGeneral::unlock();
+
+ return ret;
+}
+
+void Interface_GUIListItem::select(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ bool select)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ item->get()->Select(select);
+ Interface_GUIGeneral::unlock();
+}
+
+bool Interface_GUIListItem::is_selected(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CFileItemPtr* item = static_cast<CFileItemPtr*>(handle);
+ if (!addon || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIListItem::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ if (item->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIListItem::{} - empty list item called on addon '{}'",
+ __func__, addon->ID());
+ return false;
+ }
+
+ Interface_GUIGeneral::lock();
+ bool ret = item->get()->IsSelected();
+ Interface_GUIGeneral::unlock();
+
+ return ret;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/ListItem.h b/xbmc/addons/interfaces/gui/ListItem.h
new file mode 100644
index 0000000..70e5c6a
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/ListItem.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/list_item.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/ListItem.h"
+ */
+ struct Interface_GUIListItem
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static KODI_GUI_LISTITEM_HANDLE create(KODI_HANDLE kodiBase,
+ const char* label,
+ const char* label2,
+ const char* path);
+ static void destroy(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle);
+ static void set_label(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle, const char* label);
+ static char* get_label2(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle);
+ static void set_label2(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* label);
+ static char* get_art(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle, const char* type);
+ static void set_art(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* type,
+ const char* image);
+ static char* get_path(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle);
+ static void set_path(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle, const char* path);
+ static char* get_property(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* key);
+ static void set_property(KODI_HANDLE kodiBase,
+ KODI_GUI_LISTITEM_HANDLE handle,
+ const char* key,
+ const char* value);
+ static void select(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle, bool select);
+ static bool is_selected(KODI_HANDLE kodiBase, KODI_GUI_LISTITEM_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/Window.cpp b/xbmc/addons/interfaces/gui/Window.cpp
new file mode 100644
index 0000000..307c339
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/Window.cpp
@@ -0,0 +1,1499 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "addons/kodi-dev-kit/include/kodi/gui/Window.h"
+
+#include "FileItem.h"
+#include "GUITranslator.h"
+#include "General.h"
+#include "ServiceBroker.h"
+#include "Window.h"
+#include "addons/Skin.h"
+#include "addons/addoninfo/AddonInfo.h"
+#include "addons/addoninfo/AddonType.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "application/Application.h"
+#include "controls/Rendering.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIRenderingControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/TextureManager.h"
+#include "input/Key.h"
+#include "messaging/ApplicationMessenger.h"
+#include "utils/FileUtils.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIWindow::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->window = new AddonToKodiFuncTable_kodi_gui_window();
+
+ /* Window creation functions */
+ addonInterface->toKodi->kodi_gui->window->create = create;
+ addonInterface->toKodi->kodi_gui->window->destroy = destroy;
+ addonInterface->toKodi->kodi_gui->window->set_callbacks = set_callbacks;
+ addonInterface->toKodi->kodi_gui->window->show = show;
+ addonInterface->toKodi->kodi_gui->window->close = close;
+ addonInterface->toKodi->kodi_gui->window->do_modal = do_modal;
+
+ /* Window control functions */
+ addonInterface->toKodi->kodi_gui->window->set_focus_id = set_focus_id;
+ addonInterface->toKodi->kodi_gui->window->get_focus_id = get_focus_id;
+ addonInterface->toKodi->kodi_gui->window->set_control_label = set_control_label;
+ addonInterface->toKodi->kodi_gui->window->set_control_visible = set_control_visible;
+ addonInterface->toKodi->kodi_gui->window->set_control_selected = set_control_selected;
+
+ /* Window property functions */
+ addonInterface->toKodi->kodi_gui->window->set_property = set_property;
+ addonInterface->toKodi->kodi_gui->window->set_property_int = set_property_int;
+ addonInterface->toKodi->kodi_gui->window->set_property_bool = set_property_bool;
+ addonInterface->toKodi->kodi_gui->window->set_property_double = set_property_double;
+ addonInterface->toKodi->kodi_gui->window->get_property = get_property;
+ addonInterface->toKodi->kodi_gui->window->get_property_int = get_property_int;
+ addonInterface->toKodi->kodi_gui->window->get_property_bool = get_property_bool;
+ addonInterface->toKodi->kodi_gui->window->get_property_double = get_property_double;
+ addonInterface->toKodi->kodi_gui->window->clear_properties = clear_properties;
+ addonInterface->toKodi->kodi_gui->window->clear_property = clear_property;
+
+ /* List item functions */
+ addonInterface->toKodi->kodi_gui->window->clear_item_list = clear_item_list;
+ addonInterface->toKodi->kodi_gui->window->add_list_item = add_list_item;
+ addonInterface->toKodi->kodi_gui->window->remove_list_item_from_position =
+ remove_list_item_from_position;
+ addonInterface->toKodi->kodi_gui->window->remove_list_item = remove_list_item;
+ addonInterface->toKodi->kodi_gui->window->get_list_item = get_list_item;
+ addonInterface->toKodi->kodi_gui->window->set_current_list_position = set_current_list_position;
+ addonInterface->toKodi->kodi_gui->window->get_current_list_position = get_current_list_position;
+ addonInterface->toKodi->kodi_gui->window->get_list_size = get_list_size;
+ addonInterface->toKodi->kodi_gui->window->set_container_property = set_container_property;
+ addonInterface->toKodi->kodi_gui->window->set_container_content = set_container_content;
+ addonInterface->toKodi->kodi_gui->window->get_current_container_id = get_current_container_id;
+
+ /* Various functions */
+ addonInterface->toKodi->kodi_gui->window->mark_dirty_region = mark_dirty_region;
+
+ /* GUI control access functions */
+ addonInterface->toKodi->kodi_gui->window->get_control_button = get_control_button;
+ addonInterface->toKodi->kodi_gui->window->get_control_edit = get_control_edit;
+ addonInterface->toKodi->kodi_gui->window->get_control_fade_label = get_control_fade_label;
+ addonInterface->toKodi->kodi_gui->window->get_control_image = get_control_image;
+ addonInterface->toKodi->kodi_gui->window->get_control_label = get_control_label;
+ addonInterface->toKodi->kodi_gui->window->get_control_progress = get_control_progress;
+ addonInterface->toKodi->kodi_gui->window->get_control_radio_button = get_control_radio_button;
+ addonInterface->toKodi->kodi_gui->window->get_control_render_addon = get_control_render_addon;
+ addonInterface->toKodi->kodi_gui->window->get_control_settings_slider =
+ get_control_settings_slider;
+ addonInterface->toKodi->kodi_gui->window->get_control_slider = get_control_slider;
+ addonInterface->toKodi->kodi_gui->window->get_control_spin = get_control_spin;
+ addonInterface->toKodi->kodi_gui->window->get_control_text_box = get_control_text_box;
+}
+
+void Interface_GUIWindow::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->window;
+}
+
+/*!
+ * Window creation functions
+ */
+//@{
+KODI_GUI_WINDOW_HANDLE Interface_GUIWindow::create(KODI_HANDLE kodiBase,
+ const char* xml_filename,
+ const char* default_skin,
+ bool as_dialog,
+ bool is_media)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon || !xml_filename || !default_skin)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (xml_filename='{}', "
+ "default_skin='{}') on addon '{}'",
+ __func__, static_cast<const void*>(xml_filename),
+ static_cast<const void*>(default_skin), addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ if (as_dialog && is_media)
+ {
+ CLog::Log(LOGWARNING,
+ "Interface_GUIWindow::{}: {}/{} - addon tries to create dialog as media window who "
+ "not allowed, contact Developer '{}' of this addon",
+ __func__, CAddonInfo::TranslateType(addon->Type()), addon->Name(), addon->Author());
+ }
+
+ RESOLUTION_INFO res;
+ std::string strSkinPath = g_SkinInfo->GetSkinPath(xml_filename, &res);
+
+ if (!CFileUtils::Exists(strSkinPath))
+ {
+ std::string str("none");
+ ADDON::AddonInfoPtr addonInfo =
+ std::make_shared<ADDON::CAddonInfo>(str, ADDON::AddonType::SKIN);
+
+ // Check for the matching folder for the skin in the fallback skins folder
+ std::string fallbackPath = URIUtils::AddFileToFolder(addon->Path(), "resources", "skins");
+ std::string basePath = URIUtils::AddFileToFolder(fallbackPath, g_SkinInfo->ID());
+
+ strSkinPath = g_SkinInfo->GetSkinPath(xml_filename, &res, basePath);
+
+ // Check for the matching folder for the skin in the fallback skins folder (if it exists)
+ if (CFileUtils::Exists(basePath))
+ {
+ addonInfo->SetPath(basePath);
+ const std::shared_ptr<ADDON::CSkinInfo> skinInfo =
+ std::make_shared<ADDON::CSkinInfo>(addonInfo, res);
+ skinInfo->Start();
+ strSkinPath = skinInfo->GetSkinPath(xml_filename, &res);
+ }
+
+ if (!CFileUtils::Exists(strSkinPath))
+ {
+ // Finally fallback to the DefaultSkin as it didn't exist in either the Kodi Skin folder or the fallback skin folder
+ addonInfo->SetPath(URIUtils::AddFileToFolder(fallbackPath, default_skin));
+ const std::shared_ptr<ADDON::CSkinInfo> skinInfo =
+ std::make_shared<ADDON::CSkinInfo>(addonInfo, res);
+
+ skinInfo->Start();
+ strSkinPath = skinInfo->GetSkinPath(xml_filename, &res);
+ if (!CFileUtils::Exists(strSkinPath))
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{}: {}/{} - XML File '{}' for Window is missing, contact "
+ "Developer '{}' of this addon",
+ __func__, CAddonInfo::TranslateType(addon->Type()), addon->Name(), strSkinPath,
+ addon->Author());
+ return nullptr;
+ }
+ }
+ }
+
+ int id = GetNextAvailableWindowId();
+ if (id < 0)
+ return nullptr;
+
+ CGUIWindow* window;
+ if (!as_dialog)
+ window = new CGUIAddonWindow(id, strSkinPath, addon, is_media);
+ else
+ window = new CGUIAddonWindowDialog(id, strSkinPath, addon);
+
+ Interface_GUIGeneral::lock();
+ CServiceBroker::GetGUI()->GetWindowManager().Add(window);
+ Interface_GUIGeneral::unlock();
+
+ if (!CServiceBroker::GetGUI()->GetWindowManager().GetWindow(id))
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - Requested window id '{}' does not exist for addon '{}'",
+ __func__, id, addon->ID());
+ delete window;
+ return nullptr;
+ }
+ window->SetCoordsRes(res);
+ return window;
+}
+
+void Interface_GUIWindow::destroy(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ CGUIWindow* pWindow =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow(pAddonWindow->GetID());
+ if (pWindow)
+ {
+ // first change to an existing window
+ if (CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == pAddonWindow->GetID() &&
+ !g_application.m_bStop)
+ {
+ if (CServiceBroker::GetGUI()->GetWindowManager().GetWindow(pAddonWindow->m_oldWindowId))
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(pAddonWindow->m_oldWindowId);
+ else // old window does not exist anymore, switch to home
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(WINDOW_HOME);
+ }
+ // Free any window properties
+ pAddonWindow->ClearProperties();
+ // free the window's resources and unload it (free all guicontrols)
+ pAddonWindow->FreeResources(true);
+
+ CServiceBroker::GetGUI()->GetWindowManager().Remove(pAddonWindow->GetID());
+ }
+ delete pAddonWindow;
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_callbacks(
+ KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_CLIENT_HANDLE clienthandle,
+ bool (*CBOnInit)(KODI_GUI_CLIENT_HANDLE),
+ bool (*CBOnFocus)(KODI_GUI_CLIENT_HANDLE, int),
+ bool (*CBOnClick)(KODI_GUI_CLIENT_HANDLE, int),
+ bool (*CBOnAction)(KODI_GUI_CLIENT_HANDLE, ADDON_ACTION),
+ void (*CBGetContextButtons)(KODI_GUI_CLIENT_HANDLE, int, gui_context_menu_pair*, unsigned int*),
+ bool (*CBOnContextButton)(KODI_GUI_CLIENT_HANDLE, int, unsigned int))
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !clienthandle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (handle='{}', clienthandle='{}') "
+ "on addon '{}'",
+ __func__, handle, clienthandle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->m_clientHandle = clienthandle;
+ pAddonWindow->CBOnInit = CBOnInit;
+ pAddonWindow->CBOnClick = CBOnClick;
+ pAddonWindow->CBOnFocus = CBOnFocus;
+ pAddonWindow->CBOnAction = CBOnAction;
+ pAddonWindow->CBGetContextButtons = CBGetContextButtons;
+ pAddonWindow->CBOnContextButton = CBOnContextButton;
+ Interface_GUIGeneral::unlock();
+}
+
+bool Interface_GUIWindow::show(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ if (pAddonWindow->m_oldWindowId != pAddonWindow->m_windowId &&
+ pAddonWindow->m_windowId != CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow())
+ pAddonWindow->m_oldWindowId = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
+
+ Interface_GUIGeneral::lock();
+ if (pAddonWindow->IsDialog())
+ dynamic_cast<CGUIAddonWindowDialog*>(pAddonWindow)->Show(true, false);
+ else
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(pAddonWindow->GetID());
+ Interface_GUIGeneral::unlock();
+
+ return true;
+}
+
+bool Interface_GUIWindow::close(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ pAddonWindow->PulseActionEvent();
+
+ Interface_GUIGeneral::lock();
+
+ // if it's a dialog, we have to close it a bit different
+ if (pAddonWindow->IsDialog())
+ dynamic_cast<CGUIAddonWindowDialog*>(pAddonWindow)->Show(false);
+ else
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(pAddonWindow->m_oldWindowId);
+ pAddonWindow->m_oldWindowId = 0;
+
+ Interface_GUIGeneral::unlock();
+
+ return true;
+}
+
+bool Interface_GUIWindow::do_modal(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ if (pAddonWindow->GetID() == CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow())
+ return true;
+
+ if (pAddonWindow->m_oldWindowId != pAddonWindow->m_windowId &&
+ pAddonWindow->m_windowId != CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow())
+ pAddonWindow->m_oldWindowId = CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow();
+
+ Interface_GUIGeneral::lock();
+ if (pAddonWindow->IsDialog())
+ dynamic_cast<CGUIAddonWindowDialog*>(pAddonWindow)->Show(true, true);
+ else
+ CServiceBroker::GetGUI()->GetWindowManager().ActivateWindow(pAddonWindow->GetID());
+ Interface_GUIGeneral::unlock();
+
+ return true;
+}
+//@}
+
+/*!
+ * Window control functions
+ */
+//@{
+bool Interface_GUIWindow::set_focus_id(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ if (!pAddonWindow->GetControl(control_id))
+ {
+ CLog::Log(LOGERROR, "Interface_GUIWindow - {}: {} - Control does not exist in window", __func__,
+ addon->Name());
+ return false;
+ }
+
+ Interface_GUIGeneral::lock();
+ CGUIMessage msg(GUI_MSG_SETFOCUS, pAddonWindow->m_windowId, control_id);
+ pAddonWindow->OnMessage(msg);
+ Interface_GUIGeneral::unlock();
+
+ return true;
+}
+
+int Interface_GUIWindow::get_focus_id(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ Interface_GUIGeneral::lock();
+ int control_id = pAddonWindow->GetFocusedControlID();
+ Interface_GUIGeneral::unlock();
+
+ if (control_id == -1)
+ CLog::Log(LOGERROR, "Interface_GUIWindow - {}: {} - No control in this window has focus",
+ __func__, addon->Name());
+
+ return control_id;
+}
+
+void Interface_GUIWindow::set_control_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ CGUIMessage msg(GUI_MSG_LABEL_SET, pAddonWindow->m_windowId, control_id);
+ msg.SetLabel(label);
+ pAddonWindow->OnMessage(msg);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_control_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ CGUIMessage msg(visible ? GUI_MSG_VISIBLE : GUI_MSG_HIDDEN, pAddonWindow->m_windowId, control_id);
+ pAddonWindow->OnMessage(msg);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_control_selected(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ bool selected)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ CGUIMessage msg(selected ? GUI_MSG_SET_SELECTED : GUI_MSG_SET_DESELECTED,
+ pAddonWindow->m_windowId, control_id);
+ pAddonWindow->OnMessage(msg);
+ Interface_GUIGeneral::unlock();
+}
+//@}
+
+/*!
+ * Window property functions
+ */
+//@{
+void Interface_GUIWindow::set_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}', value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ static_cast<const void*>(value), addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetProperty(lowerKey, value);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_property_int(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetProperty(lowerKey, value);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_property_bool(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ bool value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetProperty(lowerKey, value);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_property_double(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ double value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetProperty(lowerKey, value);
+ Interface_GUIGeneral::unlock();
+}
+
+char* Interface_GUIWindow::get_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ std::string value = pAddonWindow->GetProperty(lowerKey).asString();
+ Interface_GUIGeneral::unlock();
+
+ return strdup(value.c_str());
+}
+
+int Interface_GUIWindow::get_property_int(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ int value = static_cast<int>(pAddonWindow->GetProperty(lowerKey).asInteger());
+ Interface_GUIGeneral::unlock();
+
+ return value;
+}
+
+bool Interface_GUIWindow::get_property_bool(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ bool value = pAddonWindow->GetProperty(lowerKey).asBoolean();
+ Interface_GUIGeneral::unlock();
+
+ return value;
+}
+
+double Interface_GUIWindow::get_property_double(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return 0.0;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ double value = pAddonWindow->GetProperty(lowerKey).asDouble();
+ Interface_GUIGeneral::unlock();
+
+ return value;
+}
+
+void Interface_GUIWindow::clear_properties(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->ClearProperties();
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::clear_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ std::string lowerKey = key;
+ StringUtils::ToLower(lowerKey);
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetProperty(lowerKey, "");
+ Interface_GUIGeneral::unlock();
+}
+//@}
+
+/*!
+ * List item functions
+ */
+//@{
+void Interface_GUIWindow::clear_item_list(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->ClearList();
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::add_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_LISTITEM_HANDLE item,
+ int list_position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "item='{}') on addon '{}'",
+ __func__, kodiBase, handle, item, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CFileItemPtr* pItem(static_cast<CFileItemPtr*>(item));
+ if (pItem->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIWindow::{} - empty list item called on addon '{}'", __func__,
+ addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->AddItem(pItem, list_position);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::remove_list_item_from_position(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->RemoveItem(list_position);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::remove_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_LISTITEM_HANDLE item)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !item)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "item='{}') on addon '{}'",
+ __func__, kodiBase, handle, item, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CFileItemPtr* pItem(static_cast<CFileItemPtr*>(item));
+ if (pItem->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIWindow::{} - empty list item called on addon '{}'", __func__,
+ addon->ID());
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->RemoveItem(pItem);
+ Interface_GUIGeneral::unlock();
+}
+
+KODI_GUI_LISTITEM_HANDLE Interface_GUIWindow::get_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ Interface_GUIGeneral::lock();
+ CFileItemPtr* pItem(pAddonWindow->GetListItem(list_position));
+ if (pItem == nullptr || pItem->get() == nullptr)
+ {
+ CLog::Log(LOGERROR, "ADDON::Interface_GUIWindow - {}: {} - Index out of range", __func__,
+ addon->Name());
+
+ if (pItem)
+ {
+ delete pItem;
+ pItem = nullptr;
+ }
+ }
+ Interface_GUIGeneral::unlock();
+
+ return pItem;
+}
+
+void Interface_GUIWindow::set_current_list_position(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetCurrentListPosition(list_position);
+ Interface_GUIGeneral::unlock();
+}
+
+int Interface_GUIWindow::get_current_list_position(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ Interface_GUIGeneral::lock();
+ int listPos = pAddonWindow->GetCurrentListPosition();
+ Interface_GUIGeneral::unlock();
+
+ return listPos;
+}
+
+int Interface_GUIWindow::get_list_size(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ Interface_GUIGeneral::lock();
+ int listSize = pAddonWindow->GetListSize();
+ Interface_GUIGeneral::unlock();
+
+ return listSize;
+}
+
+void Interface_GUIWindow::set_container_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !key || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "key='{}', value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(key),
+ static_cast<const void*>(value), addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetContainerProperty(key, value);
+ Interface_GUIGeneral::unlock();
+}
+
+void Interface_GUIWindow::set_container_content(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(value),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->SetContainerContent(value);
+ Interface_GUIGeneral::unlock();
+}
+
+int Interface_GUIWindow::get_current_container_id(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ Interface_GUIGeneral::lock();
+ int id = pAddonWindow->GetCurrentContainerControlId();
+ Interface_GUIGeneral::unlock();
+
+ return id;
+}
+//@}
+
+/*!
+ * Various functions
+ */
+//@{
+void Interface_GUIWindow::mark_dirty_region(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ pAddonWindow->MarkDirtyRegion();
+ Interface_GUIGeneral::unlock();
+}
+//@}
+
+/*!
+ * GUI control access functions
+ */
+//@{
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_button(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_BUTTON,
+ "button");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_edit(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_EDIT, "edit");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_fade_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_FADELABEL,
+ "fade label");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_image(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_IMAGE, "image");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_LABEL, "label");
+}
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_progress(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_PROGRESS,
+ "progress");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_radio_button(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_RADIO,
+ "radio button");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_render_addon(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ CGUIControl* pGUIControl = static_cast<CGUIControl*>(GetControl(
+ kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_RENDERADDON, "renderaddon"));
+ if (!pGUIControl)
+ return nullptr;
+
+ CGUIAddonRenderingControl* pRenderControl =
+ new CGUIAddonRenderingControl(dynamic_cast<CGUIRenderingControl*>(pGUIControl));
+ return pRenderControl;
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_settings_slider(
+ KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle, int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_SETTINGS_SLIDER,
+ "settings slider");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_slider(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_SLIDER,
+ "slider");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_spin(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_SPINEX, "spin");
+}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::get_control_text_box(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id)
+{
+ return GetControl(kodiBase, handle, control_id, __func__, CGUIControl::GUICONTROL_TEXTBOX,
+ "textbox");
+}
+//@}
+
+KODI_GUI_CONTROL_HANDLE Interface_GUIWindow::GetControl(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ const char* function,
+ CGUIControl::GUICONTROLTYPES type,
+ const std::string& typeName)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonWindow* pAddonWindow = static_cast<CGUIAddonWindow*>(handle);
+ if (!addon || !pAddonWindow)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - invalid handler data (kodiBase='{}', handle='{}') on "
+ "addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return pAddonWindow->GetAddonControl(control_id, type, typeName);
+}
+
+int Interface_GUIWindow::GetNextAvailableWindowId()
+{
+ Interface_GUIGeneral::lock();
+
+ // if window WINDOW_ADDON_END is in use it means addon can't create more windows
+ if (CServiceBroker::GetGUI()->GetWindowManager().GetWindow(WINDOW_ADDON_END))
+ {
+ Interface_GUIGeneral::unlock();
+ CLog::Log(LOGERROR,
+ "Interface_GUIWindow::{} - Maximum number of windows for binary addons reached",
+ __func__);
+ return -1;
+ }
+
+ // window id's WINDOW_ADDON_START - WINDOW_ADDON_END are reserved for addons
+ // get first window id that is not in use
+ int id = WINDOW_ADDON_START;
+ while (id < WINDOW_ADDON_END &&
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow(id) != nullptr)
+ id++;
+
+ Interface_GUIGeneral::unlock();
+ return id;
+}
+
+CGUIAddonWindow::CGUIAddonWindow(int id, const std::string& strXML, CAddonDll* addon, bool isMedia)
+ : CGUIMediaWindow(id, strXML.c_str()),
+ m_clientHandle{nullptr},
+ CBOnInit{nullptr},
+ CBOnFocus{nullptr},
+ CBOnClick{nullptr},
+ CBOnAction{nullptr},
+ CBGetContextButtons{nullptr},
+ CBOnContextButton{nullptr},
+ m_windowId(id),
+ m_oldWindowId(0),
+ m_actionEvent(true),
+ m_addon(addon),
+ m_isMedia(isMedia)
+{
+ m_loadType = LOAD_ON_GUI_INIT;
+}
+
+CGUIControl* CGUIAddonWindow::GetAddonControl(int controlId,
+ CGUIControl::GUICONTROLTYPES type,
+ const std::string& typeName)
+{
+ // Load window resources, if not already done, to have related xml content
+ // present and to let control find it
+ if (!m_windowLoaded)
+ {
+ if (!Initialize())
+ {
+ CLog::Log(LOGERROR,
+ "CGUIAddonGUI_Window::{}: {} - Window initialize failed by control id '{}' request "
+ "for '{}'",
+ __func__, m_addon->Name(), controlId, typeName);
+ return nullptr;
+ }
+ }
+
+ CGUIControl* pGUIControl = GetControl(controlId);
+ if (!pGUIControl)
+ {
+ CLog::Log(LOGERROR,
+ "CGUIAddonGUI_Window::{}: {} - Requested GUI control Id '{}' for '{}' not present!",
+ __func__, m_addon->Name(), controlId, typeName);
+ return nullptr;
+ }
+ else if (pGUIControl->GetControlType() != type)
+ {
+ CLog::Log(LOGERROR,
+ "CGUIAddonGUI_Window::{}: {} - Requested GUI control Id '{}' not the type '{}'!",
+ __func__, m_addon->Name(), controlId, typeName);
+ return nullptr;
+ }
+
+ return pGUIControl;
+}
+
+bool CGUIAddonWindow::OnAction(const CAction& action)
+{
+ // Let addon decide whether it wants to handle action first
+ if (CBOnAction &&
+ CBOnAction(m_clientHandle, CAddonGUITranslator::TranslateActionIdToAddon(action.GetID())))
+ return true;
+
+ return CGUIWindow::OnAction(action);
+}
+
+bool CGUIAddonWindow::OnMessage(CGUIMessage& message)
+{
+ switch (message.GetMessage())
+ {
+ case GUI_MSG_WINDOW_DEINIT:
+ {
+ return CGUIMediaWindow::OnMessage(message);
+ }
+ break;
+
+ case GUI_MSG_WINDOW_INIT:
+ {
+ CGUIMediaWindow::OnMessage(message);
+
+ if (CBOnInit)
+ CBOnInit(m_clientHandle);
+ return true;
+ }
+ break;
+
+ case GUI_MSG_FOCUSED:
+ {
+ if (m_viewControl.HasControl(message.GetControlId()) &&
+ m_viewControl.GetCurrentControl() != message.GetControlId())
+ {
+ m_viewControl.SetFocused();
+ return true;
+ }
+ // check if our focused control is one of our category buttons
+ int iControl = message.GetControlId();
+ if (CBOnFocus)
+ CBOnFocus(m_clientHandle, iControl);
+ }
+ break;
+
+ case GUI_MSG_NOTIFY_ALL:
+ {
+ // most messages from GUI_MSG_NOTIFY_ALL break container content, whitelist working ones.
+ if (message.GetParam1() == GUI_MSG_PAGE_CHANGE ||
+ message.GetParam1() == GUI_MSG_WINDOW_RESIZE)
+ return CGUIMediaWindow::OnMessage(message);
+ return true;
+ }
+
+ case GUI_MSG_CLICKED:
+ {
+ int iControl = message.GetSenderId();
+ if (iControl && iControl != this->GetID())
+ {
+ CGUIControl* controlClicked = this->GetControl(iControl);
+
+ // The old python way used to check list AND SELECITEM method or if its a button, checkmark.
+ // Its done this way for now to allow other controls without a python version like togglebutton to still raise a onAction event
+ if (controlClicked) // Will get problems if we the id is not on the window and we try to do GetControlType on it. So check to make sure it exists
+ {
+ if ((controlClicked->IsContainer() && (message.GetParam1() == ACTION_SELECT_ITEM ||
+ message.GetParam1() == ACTION_MOUSE_LEFT_CLICK)) ||
+ !controlClicked->IsContainer())
+ {
+ if (CBOnClick)
+ return CBOnClick(m_clientHandle, iControl);
+ }
+ else if (controlClicked->IsContainer() &&
+ (message.GetParam1() == ACTION_MOUSE_RIGHT_CLICK ||
+ message.GetParam1() == ACTION_CONTEXT_MENU))
+ {
+ if (CBOnAction)
+ {
+ // Check addon want to handle right click for a context menu, if
+ // not used from addon becomes "GetContextButtons(...)" called.
+ if (CBOnAction(m_clientHandle, ADDON_ACTION_CONTEXT_MENU))
+ return true;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ return CGUIMediaWindow::OnMessage(message);
+}
+
+void CGUIAddonWindow::AllocResources(bool forceLoad /*= false */)
+{
+ std::string tmpDir = URIUtils::GetDirectory(GetProperty("xmlfile").asString());
+ std::string fallbackMediaPath;
+ URIUtils::GetParentPath(tmpDir, fallbackMediaPath);
+ URIUtils::RemoveSlashAtEnd(fallbackMediaPath);
+ m_mediaDir = fallbackMediaPath;
+
+ CServiceBroker::GetGUI()->GetTextureManager().AddTexturePath(m_mediaDir);
+ CGUIMediaWindow::AllocResources(forceLoad);
+ CServiceBroker::GetGUI()->GetTextureManager().RemoveTexturePath(m_mediaDir);
+}
+
+void CGUIAddonWindow::Render()
+{
+ CServiceBroker::GetGUI()->GetTextureManager().AddTexturePath(m_mediaDir);
+ CGUIMediaWindow::Render();
+ CServiceBroker::GetGUI()->GetTextureManager().RemoveTexturePath(m_mediaDir);
+}
+
+void CGUIAddonWindow::AddItem(CFileItemPtr* fileItem, int itemPosition)
+{
+ if (itemPosition == -1 || itemPosition > m_vecItems->Size())
+ {
+ m_vecItems->Add(*fileItem);
+ }
+ else if (itemPosition < -1 && !(itemPosition - 1 < m_vecItems->Size()))
+ {
+ m_vecItems->AddFront(*fileItem, 0);
+ }
+ else
+ {
+ m_vecItems->AddFront(*fileItem, itemPosition);
+ }
+ m_viewControl.SetItems(*m_vecItems);
+ UpdateButtons();
+}
+
+void CGUIAddonWindow::RemoveItem(int itemPosition)
+{
+ m_vecItems->Remove(itemPosition);
+ m_viewControl.SetItems(*m_vecItems);
+ UpdateButtons();
+}
+
+void CGUIAddonWindow::RemoveItem(CFileItemPtr* fileItem)
+{
+ m_vecItems->Remove(fileItem->get());
+ m_viewControl.SetItems(*m_vecItems);
+ UpdateButtons();
+}
+
+int CGUIAddonWindow::GetCurrentListPosition()
+{
+ return m_viewControl.GetSelectedItem();
+}
+
+void CGUIAddonWindow::SetCurrentListPosition(int item)
+{
+ m_viewControl.SetSelectedItem(item);
+}
+
+int CGUIAddonWindow::GetListSize()
+{
+ return m_vecItems->Size();
+}
+
+CFileItemPtr* CGUIAddonWindow::GetListItem(int position)
+{
+ if (position < 0 || position >= m_vecItems->Size())
+ return nullptr;
+ return new CFileItemPtr(m_vecItems->Get(position));
+}
+
+void CGUIAddonWindow::ClearList()
+{
+ ClearFileItems();
+
+ m_viewControl.SetItems(*m_vecItems);
+ UpdateButtons();
+}
+
+void CGUIAddonWindow::SetContainerProperty(const std::string& key, const std::string& value)
+{
+ m_vecItems->SetProperty(key, value);
+}
+
+void CGUIAddonWindow::SetContainerContent(const std::string& value)
+{
+ m_vecItems->SetContent(value);
+}
+
+int CGUIAddonWindow::GetCurrentContainerControlId()
+{
+ return m_viewControl.GetCurrentControl();
+}
+
+void CGUIAddonWindow::GetContextButtons(int itemNumber, CContextButtons& buttons)
+{
+ gui_context_menu_pair c_buttons[ADDON_MAX_CONTEXT_ENTRIES] = {};
+ unsigned int size = ADDON_MAX_CONTEXT_ENTRIES;
+ if (CBGetContextButtons)
+ {
+ CBGetContextButtons(m_clientHandle, itemNumber, c_buttons, &size);
+ for (unsigned int i = 0; i < size; ++i)
+ buttons.push_back(std::pair<unsigned int, std::string>(c_buttons[i].id, c_buttons[i].name));
+ }
+}
+
+bool CGUIAddonWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
+{
+ if (CBOnContextButton)
+ return CBOnContextButton(m_clientHandle, itemNumber, static_cast<unsigned int>(button));
+ return false;
+}
+
+void CGUIAddonWindow::WaitForActionEvent(unsigned int timeout)
+{
+ m_actionEvent.Wait(std::chrono::milliseconds(timeout));
+ m_actionEvent.Reset();
+}
+
+void CGUIAddonWindow::PulseActionEvent()
+{
+ m_actionEvent.Set();
+}
+
+void CGUIAddonWindow::SetupShares()
+{
+ UpdateButtons();
+}
+
+
+CGUIAddonWindowDialog::CGUIAddonWindowDialog(int id, const std::string& strXML, CAddonDll* addon)
+ : CGUIAddonWindow(id, strXML, addon, false), m_bRunning(false)
+{
+}
+
+void CGUIAddonWindowDialog::Show(bool show /* = true */, bool modal /* = true*/)
+{
+ if (modal)
+ {
+ unsigned int count = CServiceBroker::GetWinSystem()->GetGfxContext().exit();
+ CServiceBroker::GetAppMessenger()->SendMsg(TMSG_GUI_ADDON_DIALOG, 0, show ? 1 : 0,
+ static_cast<void*>(this));
+ CServiceBroker::GetWinSystem()->GetGfxContext().restore(count);
+ }
+ else
+ CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ADDON_DIALOG, 0, show ? 1 : 0,
+ static_cast<void*>(this));
+}
+
+void CGUIAddonWindowDialog::Show_Internal(bool show /* = true */)
+{
+ if (show)
+ {
+ m_bRunning = true;
+ CServiceBroker::GetGUI()->GetWindowManager().RegisterDialog(this);
+
+ // activate this window...
+ CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID, GetID());
+ OnMessage(msg);
+
+ // this dialog is derived from GUIMediaWindow
+ // make sure it is rendered last
+ m_renderOrder = RENDER_ORDER_DIALOG;
+ while (m_bRunning)
+ {
+ if (!ProcessRenderLoop(false))
+ break;
+ }
+ }
+ else // hide
+ {
+ m_bRunning = false;
+
+ CGUIMessage msg(GUI_MSG_WINDOW_DEINIT, 0, 0);
+ OnMessage(msg);
+
+ CServiceBroker::GetGUI()->GetWindowManager().RemoveDialog(GetID());
+ }
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/Window.h b/xbmc/addons/interfaces/gui/Window.h
new file mode 100644
index 0000000..dad0737
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/Window.h
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/window.h"
+#include "threads/Event.h"
+#include "windows/GUIMediaWindow.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+ struct gui_context_menu_pair;
+
+ namespace ADDON
+ {
+ class CAddonDll;
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/Window.h"
+ */
+ struct Interface_GUIWindow
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ /* Window creation functions */
+ static KODI_GUI_WINDOW_HANDLE create(KODI_HANDLE kodiBase,
+ const char* xml_filename,
+ const char* default_skin,
+ bool as_dialog,
+ bool is_media);
+ static void destroy(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static void set_callbacks(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_CLIENT_HANDLE clienthandle,
+ bool (*CBInit)(KODI_GUI_CLIENT_HANDLE),
+ bool (*CBFocus)(KODI_GUI_CLIENT_HANDLE, int),
+ bool (*CBClick)(KODI_GUI_CLIENT_HANDLE, int),
+ bool (*CBOnAction)(KODI_GUI_CLIENT_HANDLE, ADDON_ACTION),
+ void (*CBGetContextButtons)(KODI_GUI_CLIENT_HANDLE,
+ int,
+ gui_context_menu_pair*,
+ unsigned int*),
+ bool (*CBOnContextButton)(KODI_GUI_CLIENT_HANDLE, int, unsigned int));
+ static bool show(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static bool close(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static bool do_modal(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+
+ /* Window control functions */
+ static bool set_focus_id(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle, int control_id);
+ static int get_focus_id(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static void set_control_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ const char* label);
+ static void set_control_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ bool visible);
+ static void set_control_selected(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ bool selected);
+
+ /* Window property functions */
+ static void set_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ const char* value);
+ static void set_property_int(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ int value);
+ static void set_property_bool(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ bool value);
+ static void set_property_double(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ double value);
+ static char* get_property(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle, const char* key);
+ static int get_property_int(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key);
+ static bool get_property_bool(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key);
+ static double get_property_double(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key);
+ static void clear_properties(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static void clear_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key);
+
+ /* List item functions */
+ static void clear_item_list(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static void add_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_LISTITEM_HANDLE item,
+ int list_position);
+ static void remove_list_item_from_position(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position);
+ static void remove_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ KODI_GUI_LISTITEM_HANDLE item);
+ static KODI_GUI_LISTITEM_HANDLE get_list_item(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position);
+ static void set_current_list_position(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int list_position);
+ static int get_current_list_position(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static int get_list_size(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+ static void set_container_property(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* key,
+ const char* value);
+ static void set_container_content(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ const char* value);
+ static int get_current_container_id(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+
+ /* Various functions */
+ static void mark_dirty_region(KODI_HANDLE kodiBase, KODI_GUI_WINDOW_HANDLE handle);
+
+ /* GUI control access functions */
+ static KODI_GUI_CONTROL_HANDLE get_control_button(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_edit(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_fade_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_image(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_label(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_radio_button(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_progress(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_render_addon(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_settings_slider(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_slider(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_spin(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ static KODI_GUI_CONTROL_HANDLE get_control_text_box(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id);
+ //@}
+
+ private:
+ static KODI_GUI_CONTROL_HANDLE GetControl(KODI_HANDLE kodiBase,
+ KODI_GUI_WINDOW_HANDLE handle,
+ int control_id,
+ const char* function,
+ CGUIControl::GUICONTROLTYPES type,
+ const std::string& typeName);
+ static int GetNextAvailableWindowId();
+ };
+
+ class CGUIAddonWindow : public CGUIMediaWindow
+ {
+ friend struct Interface_GUIWindow;
+
+ public:
+ CGUIAddonWindow(int id, const std::string& strXML, ADDON::CAddonDll* addon, bool isMedia);
+ ~CGUIAddonWindow() override = default;
+
+ bool OnMessage(CGUIMessage& message) override;
+ bool OnAction(const CAction& action) override;
+ void AllocResources(bool forceLoad = false) override;
+ void Render() override;
+ bool IsMediaWindow() const override { return m_isMedia; }
+
+ /* Addon to Kodi call functions */
+ void PulseActionEvent();
+ void AddItem(CFileItemPtr* fileItem, int itemPosition);
+ void RemoveItem(int itemPosition);
+ void RemoveItem(CFileItemPtr* fileItem);
+ void ClearList();
+ CFileItemPtr* GetListItem(int position);
+ int GetListSize();
+ int GetCurrentListPosition();
+ void SetCurrentListPosition(int item);
+ void SetContainerProperty(const std::string& key, const std::string& value);
+ void SetContainerContent(const std::string& value);
+ int GetCurrentContainerControlId();
+ CGUIControl* GetAddonControl(int controlId,
+ CGUIControl::GUICONTROLTYPES type,
+ const std::string& typeName);
+
+ protected:
+ void GetContextButtons(int itemNumber, CContextButtons& buttons) override;
+ bool OnContextButton(int itemNumber, CONTEXT_BUTTON button) override;
+ void SetupShares() override;
+
+ /* kodi to addon callback function addresses */
+ KODI_GUI_CLIENT_HANDLE m_clientHandle;
+ bool (*CBOnInit)(KODI_GUI_CLIENT_HANDLE cbhdl);
+ bool (*CBOnFocus)(KODI_GUI_CLIENT_HANDLE cbhdl, int controlId);
+ bool (*CBOnClick)(KODI_GUI_CLIENT_HANDLE cbhdl, int controlId);
+ bool (*CBOnAction)(KODI_GUI_CLIENT_HANDLE cbhdl, ADDON_ACTION actionId);
+ void (*CBGetContextButtons)(KODI_GUI_CLIENT_HANDLE cbhdl,
+ int itemNumber,
+ gui_context_menu_pair* buttons,
+ unsigned int* size);
+ bool (*CBOnContextButton)(KODI_GUI_CLIENT_HANDLE cbhdl, int itemNumber, unsigned int button);
+
+ const int m_windowId;
+ int m_oldWindowId;
+
+ private:
+ void WaitForActionEvent(unsigned int timeout);
+
+ CEvent m_actionEvent;
+ ADDON::CAddonDll* m_addon;
+ std::string m_mediaDir;
+ bool m_isMedia;
+ };
+
+ class CGUIAddonWindowDialog : public CGUIAddonWindow
+ {
+ public:
+ CGUIAddonWindowDialog(int id, const std::string& strXML, ADDON::CAddonDll* addon);
+
+ bool IsDialogRunning() const override { return m_bRunning; }
+ bool IsDialog() const override { return true; }
+ bool IsModalDialog() const override { return true; }
+
+ void Show(bool show = true, bool modal = true);
+ void Show_Internal(bool show = true);
+
+ private:
+ bool m_bRunning;
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Button.cpp b/xbmc/addons/interfaces/gui/controls/Button.cpp
new file mode 100644
index 0000000..24a9994
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Button.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Button.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Button.h"
+#include "guilib/GUIButtonControl.h"
+#include "utils/StringUtils.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlButton::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_button =
+ new AddonToKodiFuncTable_kodi_gui_control_button();
+
+ addonInterface->toKodi->kodi_gui->control_button->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_button->set_enabled = set_enabled;
+
+ addonInterface->toKodi->kodi_gui->control_button->set_label = set_label;
+ addonInterface->toKodi->kodi_gui->control_button->get_label = get_label;
+
+ addonInterface->toKodi->kodi_gui->control_button->set_label2 = set_label2;
+ addonInterface->toKodi->kodi_gui->control_button->get_label2 = get_label2;
+}
+
+void Interface_GUIControlButton::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_button;
+}
+
+void Interface_GUIControlButton::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlButton::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enabled);
+}
+
+void Interface_GUIControlButton::set_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetLabel(label);
+}
+
+char* Interface_GUIControlButton::get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetLabel().c_str());
+}
+
+void Interface_GUIControlButton::set_label2(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetLabel2(label);
+}
+
+char* Interface_GUIControlButton::get_label2(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIButtonControl* control = static_cast<CGUIButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlButton::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetLabel2().c_str());
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Button.h b/xbmc/addons/interfaces/gui/controls/Button.h
new file mode 100644
index 0000000..221ae4e
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Button.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/button.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Button.h"
+ */
+ struct Interface_GUIControlButton
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void set_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_label2(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label2(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/CMakeLists.txt b/xbmc/addons/interfaces/gui/controls/CMakeLists.txt
new file mode 100644
index 0000000..0a708c6
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(SOURCES Button.cpp
+ Edit.cpp
+ FadeLabel.cpp
+ Image.cpp
+ Label.cpp
+ Progress.cpp
+ RadioButton.cpp
+ Rendering.cpp
+ SettingsSlider.cpp
+ Slider.cpp
+ Spin.cpp
+ TextBox.cpp)
+
+set(HEADERS Button.h
+ Edit.h
+ FadeLabel.h
+ Image.h
+ Label.h
+ Progress.h
+ RadioButton.h
+ Rendering.h
+ SettingsSlider.h
+ Slider.h
+ Spin.h
+ TextBox.h)
+
+core_add_library(addons_interfaces_gui_controls)
diff --git a/xbmc/addons/interfaces/gui/controls/Edit.cpp b/xbmc/addons/interfaces/gui/controls/Edit.cpp
new file mode 100644
index 0000000..b537279
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Edit.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Edit.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Edit.h"
+#include "guilib/GUIEditControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlEdit::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_edit = new AddonToKodiFuncTable_kodi_gui_control_edit();
+
+ addonInterface->toKodi->kodi_gui->control_edit->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_edit->set_enabled = set_enabled;
+ addonInterface->toKodi->kodi_gui->control_edit->set_input_type = set_input_type;
+ addonInterface->toKodi->kodi_gui->control_edit->set_label = set_label;
+ addonInterface->toKodi->kodi_gui->control_edit->get_label = get_label;
+ addonInterface->toKodi->kodi_gui->control_edit->set_text = set_text;
+ addonInterface->toKodi->kodi_gui->control_edit->get_text = get_text;
+ addonInterface->toKodi->kodi_gui->control_edit->set_cursor_position = set_cursor_position;
+ addonInterface->toKodi->kodi_gui->control_edit->get_cursor_position = get_cursor_position;
+}
+
+void Interface_GUIControlEdit::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_edit;
+}
+
+void Interface_GUIControlEdit::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlEdit::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enable)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enable);
+}
+
+void Interface_GUIControlEdit::set_input_type(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int type,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "heading='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(heading),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIEditControl::INPUT_TYPE kodiType;
+ switch (static_cast<AddonGUIInputType>(type))
+ {
+ case ADDON_INPUT_TYPE_TEXT:
+ kodiType = CGUIEditControl::INPUT_TYPE_TEXT;
+ break;
+ case ADDON_INPUT_TYPE_NUMBER:
+ kodiType = CGUIEditControl::INPUT_TYPE_NUMBER;
+ break;
+ case ADDON_INPUT_TYPE_SECONDS:
+ kodiType = CGUIEditControl::INPUT_TYPE_SECONDS;
+ break;
+ case ADDON_INPUT_TYPE_TIME:
+ kodiType = CGUIEditControl::INPUT_TYPE_TIME;
+ break;
+ case ADDON_INPUT_TYPE_DATE:
+ kodiType = CGUIEditControl::INPUT_TYPE_DATE;
+ break;
+ case ADDON_INPUT_TYPE_IPADDRESS:
+ kodiType = CGUIEditControl::INPUT_TYPE_IPADDRESS;
+ break;
+ case ADDON_INPUT_TYPE_PASSWORD:
+ kodiType = CGUIEditControl::INPUT_TYPE_PASSWORD;
+ break;
+ case ADDON_INPUT_TYPE_PASSWORD_MD5:
+ kodiType = CGUIEditControl::INPUT_TYPE_PASSWORD_MD5;
+ break;
+ case ADDON_INPUT_TYPE_SEARCH:
+ kodiType = CGUIEditControl::INPUT_TYPE_SEARCH;
+ break;
+ case ADDON_INPUT_TYPE_FILTER:
+ kodiType = CGUIEditControl::INPUT_TYPE_FILTER;
+ break;
+ case ADDON_INPUT_TYPE_READONLY:
+ default:
+ kodiType = CGUIEditControl::INPUT_TYPE_PASSWORD_NUMBER_VERIFY_NEW;
+ }
+
+ control->SetInputType(kodiType, heading);
+}
+
+void Interface_GUIControlEdit::set_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetLabel(label);
+}
+
+char* Interface_GUIControlEdit::get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetLabel().c_str());
+}
+
+void Interface_GUIControlEdit::set_text(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "text='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(text),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetLabel2(text);
+}
+
+char* Interface_GUIControlEdit::get_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetLabel2().c_str());
+}
+
+void Interface_GUIControlEdit::set_cursor_position(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ unsigned int position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetCursorPosition(position);
+}
+
+unsigned int Interface_GUIControlEdit::get_cursor_position(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIEditControl* control = static_cast<CGUIEditControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlEdit::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0;
+ }
+
+ return control->GetCursorPosition();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Edit.h b/xbmc/addons/interfaces/gui/controls/Edit.h
new file mode 100644
index 0000000..9dda1e2
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Edit.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/edit.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Edit.h"
+ */
+ struct Interface_GUIControlEdit
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void set_input_type(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int type,
+ const char* heading);
+
+ static void set_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* text);
+ static char* get_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_cursor_position(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ unsigned int position);
+ static unsigned int get_cursor_position(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/FadeLabel.cpp b/xbmc/addons/interfaces/gui/controls/FadeLabel.cpp
new file mode 100644
index 0000000..13c5604
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/FadeLabel.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "FadeLabel.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/FadeLabel.h"
+#include "guilib/GUIFadeLabelControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlFadeLabel::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_fade_label =
+ new AddonToKodiFuncTable_kodi_gui_control_fade_label();
+
+ addonInterface->toKodi->kodi_gui->control_fade_label->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_fade_label->add_label = add_label;
+ addonInterface->toKodi->kodi_gui->control_fade_label->get_label = get_label;
+ addonInterface->toKodi->kodi_gui->control_fade_label->set_scrolling = set_scrolling;
+ addonInterface->toKodi->kodi_gui->control_fade_label->reset = reset;
+}
+
+void Interface_GUIControlFadeLabel::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_fade_label;
+}
+
+void Interface_GUIControlFadeLabel::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIFadeLabelControl* control = static_cast<CGUIFadeLabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlFadeLabel::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlFadeLabel::add_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIFadeLabelControl* control = static_cast<CGUIFadeLabelControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlFadeLabel::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}', label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_ADD, control->GetParentID(), control->GetID());
+ msg.SetLabel(label);
+ control->OnMessage(msg);
+}
+
+char* Interface_GUIControlFadeLabel::get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIFadeLabelControl* control = static_cast<CGUIFadeLabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlFadeLabel::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ CGUIMessage msg(GUI_MSG_ITEM_SELECTED, control->GetParentID(), control->GetID());
+ control->OnMessage(msg);
+ std::string text = msg.GetLabel();
+ return strdup(text.c_str());
+}
+
+void Interface_GUIControlFadeLabel::set_scrolling(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool scroll)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIFadeLabelControl* control = static_cast<CGUIFadeLabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlFadeLabel::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetScrolling(scroll);
+}
+
+void Interface_GUIControlFadeLabel::reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIFadeLabelControl* control = static_cast<CGUIFadeLabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlFadeLabel::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, control->GetParentID(), control->GetID());
+ control->OnMessage(msg);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/FadeLabel.h b/xbmc/addons/interfaces/gui/controls/FadeLabel.h
new file mode 100644
index 0000000..2c3cd68
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/FadeLabel.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/fade_label.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/FadeLabel.h"
+ */
+ struct Interface_GUIControlFadeLabel
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+ static void set_selected(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool selected);
+
+ static void add_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_scrolling(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool scroll);
+ static void reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Image.cpp b/xbmc/addons/interfaces/gui/controls/Image.cpp
new file mode 100644
index 0000000..88f368c
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Image.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Image.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Image.h"
+#include "guilib/GUIImage.h"
+#include "utils/log.h"
+
+using namespace KODI;
+
+namespace ADDON
+{
+
+void Interface_GUIControlImage::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_image =
+ new AddonToKodiFuncTable_kodi_gui_control_image();
+
+ addonInterface->toKodi->kodi_gui->control_image->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_image->set_filename = set_filename;
+ addonInterface->toKodi->kodi_gui->control_image->set_color_diffuse = set_color_diffuse;
+}
+
+void Interface_GUIControlImage::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_image;
+}
+
+void Interface_GUIControlImage::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIImage* control = static_cast<CGUIImage*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlImage::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlImage::set_filename(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* filename,
+ bool use_cache)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIImage* control = static_cast<CGUIImage*>(handle);
+ if (!addon || !control || !filename)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlImage::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "filename='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(filename),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFileName(filename, false, use_cache);
+}
+
+void Interface_GUIControlImage::set_color_diffuse(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ uint32_t colorDiffuse)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIImage* control = static_cast<CGUIImage*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlImage::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetColorDiffuse(GUILIB::GUIINFO::CGUIInfoColor(colorDiffuse));
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Image.h b/xbmc/addons/interfaces/gui/controls/Image.h
new file mode 100644
index 0000000..b12bece
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Image.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/image.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Image.h"
+ */
+ struct Interface_GUIControlImage
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_filename(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* filename,
+ bool use_cache);
+ static void set_color_diffuse(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ uint32_t color_diffuse);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Label.cpp b/xbmc/addons/interfaces/gui/controls/Label.cpp
new file mode 100644
index 0000000..3922e3f
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Label.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Label.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Label.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUILabelControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlLabel::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_label =
+ new AddonToKodiFuncTable_kodi_gui_control_label();
+
+ addonInterface->toKodi->kodi_gui->control_label->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_label->set_label = set_label;
+ addonInterface->toKodi->kodi_gui->control_label->get_label = get_label;
+}
+
+void Interface_GUIControlLabel::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_label;
+}
+
+void Interface_GUIControlLabel::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUILabelControl* control = static_cast<CGUILabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlLabel::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlLabel::set_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUILabelControl* control = static_cast<CGUILabelControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlLabel::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_SET, control->GetParentID(), control->GetID());
+ msg.SetLabel(label);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+char* Interface_GUIControlLabel::get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUILabelControl* control = static_cast<CGUILabelControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlLabel::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetDescription().c_str());
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Label.h b/xbmc/addons/interfaces/gui/controls/Label.h
new file mode 100644
index 0000000..020c3d5
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Label.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/label.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Label.h"
+ */
+ struct Interface_GUIControlLabel
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+
+ static void set_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Progress.cpp b/xbmc/addons/interfaces/gui/controls/Progress.cpp
new file mode 100644
index 0000000..639d079
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Progress.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Progress.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Progress.h"
+#include "guilib/GUIProgressControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlProgress::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_progress =
+ new AddonToKodiFuncTable_kodi_gui_control_progress();
+
+ addonInterface->toKodi->kodi_gui->control_progress->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_progress->set_percentage = set_percentage;
+ addonInterface->toKodi->kodi_gui->control_progress->get_percentage = get_percentage;
+}
+
+void Interface_GUIControlProgress::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_progress;
+}
+
+void Interface_GUIControlProgress::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIProgressControl* control = static_cast<CGUIProgressControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlProgress::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlProgress::set_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float percent)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIProgressControl* control = static_cast<CGUIProgressControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlProgress::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetPercentage(percent);
+}
+
+float Interface_GUIControlProgress::get_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIProgressControl* control = static_cast<CGUIProgressControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlProgress::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetPercentage();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Progress.h b/xbmc/addons/interfaces/gui/controls/Progress.h
new file mode 100644
index 0000000..c3368fa
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Progress.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/progress.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Progress.h"
+ */
+ struct Interface_GUIControlProgress
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+
+ static void set_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float percent);
+ static float get_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/RadioButton.cpp b/xbmc/addons/interfaces/gui/controls/RadioButton.cpp
new file mode 100644
index 0000000..9d3b826
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/RadioButton.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "RadioButton.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/RadioButton.h"
+#include "guilib/GUIRadioButtonControl.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlRadioButton::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_radio_button =
+ new AddonToKodiFuncTable_kodi_gui_control_radio_button();
+
+ addonInterface->toKodi->kodi_gui->control_radio_button->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_radio_button->set_enabled = set_enabled;
+
+ addonInterface->toKodi->kodi_gui->control_radio_button->set_label = set_label;
+ addonInterface->toKodi->kodi_gui->control_radio_button->get_label = get_label;
+
+ addonInterface->toKodi->kodi_gui->control_radio_button->set_selected = set_selected;
+ addonInterface->toKodi->kodi_gui->control_radio_button->is_selected = is_selected;
+}
+
+void Interface_GUIControlRadioButton::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_radio_button;
+}
+
+void Interface_GUIControlRadioButton::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlRadioButton::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enabled);
+}
+
+void Interface_GUIControlRadioButton::set_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}', label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetLabel(label);
+}
+
+char* Interface_GUIControlRadioButton::get_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetLabel().c_str());
+}
+
+void Interface_GUIControlRadioButton::set_selected(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool selected)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetSelected(selected);
+}
+
+bool Interface_GUIControlRadioButton::is_selected(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIRadioButtonControl* control = static_cast<CGUIRadioButtonControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlRadioButton::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return false;
+ }
+
+ return control->IsSelected();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/RadioButton.h b/xbmc/addons/interfaces/gui/controls/RadioButton.h
new file mode 100644
index 0000000..dd7ed4e
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/RadioButton.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/radio_button.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/RadioButton.h"
+ */
+ struct Interface_GUIControlRadioButton
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void set_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* label);
+ static char* get_label(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_selected(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool selected);
+ static bool is_selected(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Rendering.cpp b/xbmc/addons/interfaces/gui/controls/Rendering.cpp
new file mode 100644
index 0000000..a26a27f
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Rendering.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Rendering.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/interfaces/gui/General.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Rendering.h"
+#include "guilib/GUIRenderingControl.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlAddonRendering::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_rendering =
+ new AddonToKodiFuncTable_kodi_gui_control_rendering();
+
+ addonInterface->toKodi->kodi_gui->control_rendering->set_callbacks = set_callbacks;
+ addonInterface->toKodi->kodi_gui->control_rendering->destroy = destroy;
+}
+
+void Interface_GUIControlAddonRendering::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_rendering;
+}
+
+void Interface_GUIControlAddonRendering::set_callbacks(
+ KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ KODI_GUI_CLIENT_HANDLE clienthandle,
+ bool (*createCB)(KODI_GUI_CLIENT_HANDLE, int, int, int, int, ADDON_HARDWARE_CONTEXT),
+ void (*renderCB)(KODI_GUI_CLIENT_HANDLE),
+ void (*stopCB)(KODI_GUI_CLIENT_HANDLE),
+ bool (*dirtyCB)(KODI_GUI_CLIENT_HANDLE))
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonRenderingControl* control = static_cast<CGUIAddonRenderingControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlAddonRendering::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ control->m_clientHandle = clienthandle;
+ control->CBCreate = createCB;
+ control->CBRender = renderCB;
+ control->CBStop = stopCB;
+ control->CBDirty = dirtyCB;
+ control->m_addon = addon;
+ Interface_GUIGeneral::unlock();
+
+ control->m_control->InitCallback(control);
+}
+
+void Interface_GUIControlAddonRendering::destroy(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUIAddonRenderingControl* control = static_cast<CGUIAddonRenderingControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlAddonRendering::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ Interface_GUIGeneral::lock();
+ static_cast<CGUIAddonRenderingControl*>(handle)->Delete();
+ Interface_GUIGeneral::unlock();
+}
+
+
+CGUIAddonRenderingControl::CGUIAddonRenderingControl(CGUIRenderingControl* control)
+ : CBCreate{nullptr},
+ CBRender{nullptr},
+ CBStop{nullptr},
+ CBDirty{nullptr},
+ m_clientHandle{nullptr},
+ m_addon{nullptr},
+ m_control{control},
+ m_refCount{1}
+{
+}
+
+bool CGUIAddonRenderingControl::Create(int x, int y, int w, int h, void* device)
+{
+ if (CBCreate)
+ {
+ if (CBCreate(m_clientHandle, x, y, w, h, device))
+ {
+ ++m_refCount;
+ return true;
+ }
+ }
+ return false;
+}
+
+void CGUIAddonRenderingControl::Render()
+{
+ if (CBRender)
+ {
+ CBRender(m_clientHandle);
+ }
+}
+
+void CGUIAddonRenderingControl::Stop()
+{
+ if (CBStop)
+ {
+ CBStop(m_clientHandle);
+ }
+
+ --m_refCount;
+ if (m_refCount <= 0)
+ delete this;
+}
+
+void CGUIAddonRenderingControl::Delete()
+{
+ --m_refCount;
+ if (m_refCount <= 0)
+ delete this;
+}
+
+bool CGUIAddonRenderingControl::IsDirty()
+{
+ bool ret = true;
+ if (CBDirty)
+ {
+ ret = CBDirty(m_clientHandle);
+ }
+ return ret;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Rendering.h b/xbmc/addons/interfaces/gui/controls/Rendering.h
new file mode 100644
index 0000000..dbd82d8
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Rendering.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/rendering.h"
+#include "guilib/IRenderingCallback.h"
+
+class CGUIRenderingControl;
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ class CAddonDll;
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Rendering.h"
+ */
+ struct Interface_GUIControlAddonRendering
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_callbacks(
+ KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ KODI_GUI_CLIENT_HANDLE clienthandle,
+ bool (*createCB)(KODI_GUI_CLIENT_HANDLE, int, int, int, int, ADDON_HARDWARE_CONTEXT),
+ void (*renderCB)(KODI_GUI_CLIENT_HANDLE),
+ void (*stopCB)(KODI_GUI_CLIENT_HANDLE),
+ bool (*dirtyCB)(KODI_GUI_CLIENT_HANDLE));
+ static void destroy(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ //@}
+ };
+
+ class CGUIAddonRenderingControl : public IRenderingCallback
+ {
+ friend struct Interface_GUIControlAddonRendering;
+
+ public:
+ explicit CGUIAddonRenderingControl(CGUIRenderingControl* pControl);
+ ~CGUIAddonRenderingControl() override = default;
+
+ bool Create(int x, int y, int w, int h, void* device) override;
+ void Render() override;
+ void Stop() override;
+ bool IsDirty() override;
+ virtual void Delete();
+
+ protected:
+ bool (*CBCreate)(KODI_GUI_CLIENT_HANDLE cbhdl, int x, int y, int w, int h, void* device);
+ void (*CBRender)(KODI_GUI_CLIENT_HANDLE cbhdl);
+ void (*CBStop)(KODI_GUI_CLIENT_HANDLE cbhdl);
+ bool (*CBDirty)(KODI_GUI_CLIENT_HANDLE cbhdl);
+
+ KODI_GUI_CLIENT_HANDLE m_clientHandle;
+ CAddonDll* m_addon;
+ CGUIRenderingControl* m_control;
+ int m_refCount;
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/SettingsSlider.cpp b/xbmc/addons/interfaces/gui/controls/SettingsSlider.cpp
new file mode 100644
index 0000000..c847a64
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/SettingsSlider.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "SettingsSlider.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/SettingsSlider.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUISettingsSliderControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlSettingsSlider::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_settings_slider =
+ new AddonToKodiFuncTable_kodi_gui_control_settings_slider();
+
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_enabled = set_enabled;
+
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_text = set_text;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->reset = reset;
+
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_int_range = set_int_range;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_int_value = set_int_value;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->get_int_value = get_int_value;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_int_interval = set_int_interval;
+
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_percentage = set_percentage;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->get_percentage = get_percentage;
+
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_float_range = set_float_range;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_float_value = set_float_value;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->get_float_value = get_float_value;
+ addonInterface->toKodi->kodi_gui->control_settings_slider->set_float_interval =
+ set_float_interval;
+}
+
+void Interface_GUIControlSettingsSlider::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_settings_slider;
+}
+
+void Interface_GUIControlSettingsSlider::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlSettingsSlider::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enabled);
+}
+
+void Interface_GUIControlSettingsSlider::set_text(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}', text='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(text),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_SET, control->GetParentID(), control->GetID());
+ msg.SetLabel(text);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+void Interface_GUIControlSettingsSlider::reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, control->GetParentID(), control->GetID());
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+void Interface_GUIControlSettingsSlider::set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_INT);
+ control->SetRange(start, end);
+}
+
+void Interface_GUIControlSettingsSlider::set_int_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_INT);
+ control->SetIntValue(value);
+}
+
+int Interface_GUIControlSettingsSlider::get_int_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ return control->GetIntValue();
+}
+
+void Interface_GUIControlSettingsSlider::set_int_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int interval)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetIntInterval(interval);
+}
+
+void Interface_GUIControlSettingsSlider::set_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float percent)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE);
+ control->SetPercentage(percent);
+}
+
+float Interface_GUIControlSettingsSlider::get_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetPercentage();
+}
+
+void Interface_GUIControlSettingsSlider::set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_FLOAT);
+ control->SetFloatRange(start, end);
+}
+
+void Interface_GUIControlSettingsSlider::set_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_FLOAT);
+ control->SetFloatValue(value);
+}
+
+float Interface_GUIControlSettingsSlider::get_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetFloatValue();
+}
+
+void Interface_GUIControlSettingsSlider::set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISettingsSliderControl* control = static_cast<CGUISettingsSliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSettingsSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFloatInterval(interval);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/SettingsSlider.h b/xbmc/addons/interfaces/gui/controls/SettingsSlider.h
new file mode 100644
index 0000000..425c275
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/SettingsSlider.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/settings_slider.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/SettingsSlider.h"
+ */
+ struct Interface_GUIControlSettingsSlider
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void set_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* text);
+ static void reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end);
+ static void set_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int value);
+ static int get_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_int_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int interval);
+
+ static void set_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float percent);
+ static float get_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end);
+ static void set_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float value);
+ static float get_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Slider.cpp b/xbmc/addons/interfaces/gui/controls/Slider.cpp
new file mode 100644
index 0000000..73502d8
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Slider.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Slider.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Slider.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUISliderControl.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlSlider::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_slider =
+ new AddonToKodiFuncTable_kodi_gui_control_slider();
+
+ addonInterface->toKodi->kodi_gui->control_slider->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_slider->set_enabled = set_enabled;
+
+ addonInterface->toKodi->kodi_gui->control_slider->reset = reset;
+ addonInterface->toKodi->kodi_gui->control_slider->get_description = get_description;
+
+ addonInterface->toKodi->kodi_gui->control_slider->set_int_range = set_int_range;
+ addonInterface->toKodi->kodi_gui->control_slider->set_int_value = set_int_value;
+ addonInterface->toKodi->kodi_gui->control_slider->get_int_value = get_int_value;
+ addonInterface->toKodi->kodi_gui->control_slider->set_int_interval = set_int_interval;
+
+ addonInterface->toKodi->kodi_gui->control_slider->set_percentage = set_percentage;
+ addonInterface->toKodi->kodi_gui->control_slider->get_percentage = get_percentage;
+
+ addonInterface->toKodi->kodi_gui->control_slider->set_float_range = set_float_range;
+ addonInterface->toKodi->kodi_gui->control_slider->set_float_value = set_float_value;
+ addonInterface->toKodi->kodi_gui->control_slider->get_float_value = get_float_value;
+ addonInterface->toKodi->kodi_gui->control_slider->set_float_interval = set_float_interval;
+}
+
+void Interface_GUIControlSlider::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_slider;
+}
+
+void Interface_GUIControlSlider::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlSlider::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enabled);
+}
+
+void Interface_GUIControlSlider::reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, control->GetParentID(), control->GetID());
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+char* Interface_GUIControlSlider::get_description(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetDescription().c_str());
+}
+
+void Interface_GUIControlSlider::set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_INT);
+ control->SetRange(start, end);
+}
+
+void Interface_GUIControlSlider::set_int_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_INT);
+ control->SetIntValue(value);
+}
+
+int Interface_GUIControlSlider::get_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ return control->GetIntValue();
+}
+
+void Interface_GUIControlSlider::set_int_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int interval)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetIntInterval(interval);
+}
+
+void Interface_GUIControlSlider::set_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float percent)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_PERCENTAGE);
+ control->SetPercentage(percent);
+}
+
+float Interface_GUIControlSlider::get_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetPercentage();
+}
+
+void Interface_GUIControlSlider::set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_FLOAT);
+ control->SetFloatRange(start, end);
+}
+
+void Interface_GUIControlSlider::set_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(SLIDER_CONTROL_TYPE_FLOAT);
+ control->SetFloatValue(value);
+}
+
+float Interface_GUIControlSlider::get_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetFloatValue();
+}
+
+void Interface_GUIControlSlider::set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISliderControl* control = static_cast<CGUISliderControl*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSlider::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFloatInterval(interval);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Slider.h b/xbmc/addons/interfaces/gui/controls/Slider.h
new file mode 100644
index 0000000..30afbaf
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Slider.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/slider.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Slider.h"
+ */
+ struct Interface_GUIControlSlider
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static char* get_description(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end);
+ static void set_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int value);
+ static int get_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_int_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int interval);
+
+ static void set_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float percent);
+ static float get_percentage(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end);
+ static void set_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float value);
+ static float get_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/Spin.cpp b/xbmc/addons/interfaces/gui/controls/Spin.cpp
new file mode 100644
index 0000000..b9eb6ea
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Spin.cpp
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Spin.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/Spin.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUISpinControlEx.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlSpin::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_spin = new AddonToKodiFuncTable_kodi_gui_control_spin();
+
+ addonInterface->toKodi->kodi_gui->control_spin->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_spin->set_enabled = set_enabled;
+
+ addonInterface->toKodi->kodi_gui->control_spin->set_text = set_text;
+ addonInterface->toKodi->kodi_gui->control_spin->reset = reset;
+ addonInterface->toKodi->kodi_gui->control_spin->set_type = set_type;
+
+ addonInterface->toKodi->kodi_gui->control_spin->add_string_label = add_string_label;
+ addonInterface->toKodi->kodi_gui->control_spin->set_string_value = set_string_value;
+ addonInterface->toKodi->kodi_gui->control_spin->get_string_value = get_string_value;
+
+ addonInterface->toKodi->kodi_gui->control_spin->add_int_label = add_int_label;
+ addonInterface->toKodi->kodi_gui->control_spin->set_int_range = set_int_range;
+ addonInterface->toKodi->kodi_gui->control_spin->set_int_value = set_int_value;
+ addonInterface->toKodi->kodi_gui->control_spin->get_int_value = get_int_value;
+
+ addonInterface->toKodi->kodi_gui->control_spin->set_float_range = set_float_range;
+ addonInterface->toKodi->kodi_gui->control_spin->set_float_value = set_float_value;
+ addonInterface->toKodi->kodi_gui->control_spin->get_float_value = get_float_value;
+ addonInterface->toKodi->kodi_gui->control_spin->set_float_interval = set_float_interval;
+}
+
+void Interface_GUIControlSpin::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_spin;
+}
+
+void Interface_GUIControlSpin::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlSpin::set_enabled(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool enabled)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetEnabled(enabled);
+}
+
+void Interface_GUIControlSpin::set_text(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "text='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(text),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_SET, control->GetParentID(), control->GetID());
+ msg.SetLabel(text);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+void Interface_GUIControlSpin::reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, control->GetParentID(), control->GetID());
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+void Interface_GUIControlSpin::set_type(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int type)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetType(type);
+}
+
+void Interface_GUIControlSpin::add_string_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control || !label || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}', value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ static_cast<const void*>(value), addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->AddLabel(std::string(label), std::string(value));
+}
+
+void Interface_GUIControlSpin::set_string_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control || !value)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "value='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(value),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetStringValue(std::string(value));
+}
+
+char* Interface_GUIControlSpin::get_string_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetStringValue().c_str());
+}
+
+void Interface_GUIControlSpin::add_int_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label,
+ int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control || !label)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}', "
+ "label='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(label),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->AddLabel(std::string(label), value);
+}
+
+void Interface_GUIControlSpin::set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetRange(start, end);
+}
+
+void Interface_GUIControlSpin::set_int_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetValue(value);
+}
+
+int Interface_GUIControlSpin::get_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return -1;
+ }
+
+ return control->GetValue();
+}
+
+void Interface_GUIControlSpin::set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFloatRange(start, end);
+}
+
+void Interface_GUIControlSpin::set_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float value)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFloatValue(value);
+}
+
+float Interface_GUIControlSpin::get_float_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return 0.0f;
+ }
+
+ return control->GetFloatValue();
+}
+
+void Interface_GUIControlSpin::set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUISpinControlEx* control = static_cast<CGUISpinControlEx*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlSpin::{} - invalid handler data (kodiBase='{}', handle='{}') "
+ "on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetFloatInterval(interval);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/Spin.h b/xbmc/addons/interfaces/gui/controls/Spin.h
new file mode 100644
index 0000000..1c7102e
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/Spin.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/spin.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/Spin.h"
+ */
+ struct Interface_GUIControlSpin
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void set_enabled(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool enabled);
+
+ static void set_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* text);
+ static void reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_type(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int type);
+
+ static void add_string_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label,
+ const char* value);
+ static void add_int_label(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* label,
+ int value);
+
+ static void set_string_value(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* value);
+ static char* get_string_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_int_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ int start,
+ int end);
+ static void set_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int value);
+ static int get_int_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+
+ static void set_float_range(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float start,
+ float end);
+ static void set_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, float value);
+ static float get_float_value(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_float_interval(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ float interval);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/controls/TextBox.cpp b/xbmc/addons/interfaces/gui/controls/TextBox.cpp
new file mode 100644
index 0000000..44c5f89
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/TextBox.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "TextBox.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/controls/TextBox.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUITextBox.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIControlTextBox::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->control_text_box =
+ new AddonToKodiFuncTable_kodi_gui_control_text_box();
+
+ addonInterface->toKodi->kodi_gui->control_text_box->set_visible = set_visible;
+ addonInterface->toKodi->kodi_gui->control_text_box->reset = reset;
+ addonInterface->toKodi->kodi_gui->control_text_box->set_text = set_text;
+ addonInterface->toKodi->kodi_gui->control_text_box->get_text = get_text;
+ addonInterface->toKodi->kodi_gui->control_text_box->scroll = scroll;
+ addonInterface->toKodi->kodi_gui->control_text_box->set_auto_scrolling = set_auto_scrolling;
+}
+
+void Interface_GUIControlTextBox::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->control_text_box;
+}
+
+void Interface_GUIControlTextBox::set_visible(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ bool visible)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetVisible(visible);
+}
+
+void Interface_GUIControlTextBox::reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_RESET, control->GetParentID(), control->GetID());
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+void Interface_GUIControlTextBox::set_text(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}', text='{}') on addon '{}'",
+ __func__, kodiBase, handle, static_cast<const void*>(text),
+ addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ CGUIMessage msg(GUI_MSG_LABEL_SET, control->GetParentID(), control->GetID());
+ msg.SetLabel(text);
+ CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, control->GetParentID());
+}
+
+char* Interface_GUIControlTextBox::get_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return nullptr;
+ }
+
+ return strdup(control->GetDescription().c_str());
+}
+
+void Interface_GUIControlTextBox::scroll(KODI_HANDLE kodiBase,
+ KODI_GUI_CONTROL_HANDLE handle,
+ unsigned int position)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->Scroll(position);
+}
+
+void Interface_GUIControlTextBox::set_auto_scrolling(
+ KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int delay, int time, int repeat)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ CGUITextBox* control = static_cast<CGUITextBox*>(handle);
+ if (!addon || !control)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIControlTextBox::{} - invalid handler data (kodiBase='{}', "
+ "handle='{}') on addon '{}'",
+ __func__, kodiBase, handle, addon ? addon->ID() : "unknown");
+ return;
+ }
+
+ control->SetAutoScrolling(delay, time, repeat);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/controls/TextBox.h b/xbmc/addons/interfaces/gui/controls/TextBox.h
new file mode 100644
index 0000000..09c2ff4
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/controls/TextBox.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/controls/text_box.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold general gui functions and initialize also all other gui related types not
+ * related to a instance type and usable for every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/controls/TextBox.h"
+ */
+ struct Interface_GUIControlTextBox
+ {
+
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void set_visible(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, bool visible);
+ static void reset(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void set_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, const char* text);
+ static char* get_text(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle);
+ static void scroll(KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, unsigned int position);
+ static void set_auto_scrolling(
+ KODI_HANDLE kodiBase, KODI_GUI_CONTROL_HANDLE handle, int delay, int time, int repeat);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/CMakeLists.txt b/xbmc/addons/interfaces/gui/dialogs/CMakeLists.txt
new file mode 100644
index 0000000..4dad4e9
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(SOURCES ContextMenu.cpp
+ ExtendedProgressBar.cpp
+ FileBrowser.cpp
+ Keyboard.cpp
+ Numeric.cpp
+ OK.cpp
+ Progress.cpp
+ Select.cpp
+ TextViewer.cpp
+ YesNo.cpp)
+
+set(HEADERS ContextMenu.h
+ ExtendedProgressBar.h
+ FileBrowser.h
+ Keyboard.h
+ Numeric.h
+ OK.h
+ Progress.h
+ Select.h
+ TextViewer.h
+ YesNo.h)
+
+core_add_library(addons_interfaces_gui_dialogs)
diff --git a/xbmc/addons/interfaces/gui/dialogs/ContextMenu.cpp b/xbmc/addons/interfaces/gui/dialogs/ContextMenu.cpp
new file mode 100644
index 0000000..e0e5684
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/ContextMenu.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "ContextMenu.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/ContextMenu.h"
+#include "dialogs/GUIDialogContextMenu.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogContextMenu::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogContextMenu =
+ new AddonToKodiFuncTable_kodi_gui_dialogContextMenu();
+
+ addonInterface->toKodi->kodi_gui->dialogContextMenu->open = open;
+}
+
+void Interface_GUIDialogContextMenu::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogContextMenu;
+}
+
+int Interface_GUIDialogContextMenu::open(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entries[],
+ unsigned int size)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogContextMenu::{} - invalid data", __func__);
+ return -1;
+ }
+
+ CGUIDialogContextMenu* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogContextMenu>(
+ WINDOW_DIALOG_CONTEXT_MENU);
+ if (!heading || !entries || !dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogContextMenu::{} - invalid handler data (heading='{}', "
+ "entries='{}', dialog='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(entries),
+ kodiBase, addon->ID());
+ return -1;
+ }
+
+ CContextButtons choices;
+ for (unsigned int i = 0; i < size; ++i)
+ choices.Add(i, entries[i]);
+
+ return dialog->Show(choices);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/ContextMenu.h b/xbmc/addons/interfaces/gui/dialogs/ContextMenu.h
new file mode 100644
index 0000000..7b41a28
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/ContextMenu.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/context_menu.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/ContextMenu.h"
+ */
+ struct Interface_GUIDialogContextMenu
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static int open(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entries[],
+ unsigned int size);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.cpp b/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.cpp
new file mode 100644
index 0000000..9e7f7a7
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "ExtendedProgressBar.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/ExtendedProgress.h"
+#include "dialogs/GUIDialogExtendedProgressBar.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogExtendedProgress::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress =
+ new AddonToKodiFuncTable_kodi_gui_dialogExtendedProgress();
+
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->new_dialog = new_dialog;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->delete_dialog = delete_dialog;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->get_title = get_title;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->set_title = set_title;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->get_text = get_text;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->set_text = set_text;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->is_finished = is_finished;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->mark_finished = mark_finished;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->get_percentage = get_percentage;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->set_percentage = set_percentage;
+ addonInterface->toKodi->kodi_gui->dialogExtendedProgress->set_progress = set_progress;
+}
+
+void Interface_GUIDialogExtendedProgress::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogExtendedProgress;
+}
+
+KODI_GUI_HANDLE Interface_GUIDialogExtendedProgress::new_dialog(KODI_HANDLE kodiBase,
+ const char* title)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return nullptr;
+ }
+
+ // setup the progress dialog
+ CGUIDialogExtendedProgressBar* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogExtendedProgressBar>(
+ WINDOW_DIALOG_EXT_PROGRESS);
+ if (!title || !dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid handler data (title='{}', "
+ "dialog='{}') on addon '{}'",
+ __func__, static_cast<const void*>(title), static_cast<void*>(dialog), addon->ID());
+ return nullptr;
+ }
+
+ CGUIDialogProgressBarHandle* dlgProgressHandle = dialog->GetHandle(title);
+ return dlgProgressHandle;
+}
+
+void Interface_GUIDialogExtendedProgress::delete_dialog(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid handler data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->MarkFinished();
+}
+
+char* Interface_GUIDialogExtendedProgress::get_title(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return nullptr;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid handler data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return nullptr;
+ }
+
+ return strdup(static_cast<CGUIDialogProgressBarHandle*>(handle)->Title().c_str());
+}
+
+void Interface_GUIDialogExtendedProgress::set_title(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ const char* title)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle || !title)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid handler data (handle='{}', "
+ "title='{}') on addon '{}'",
+ __func__, handle, static_cast<const void*>(title), addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->SetTitle(title);
+}
+
+char* Interface_GUIDialogExtendedProgress::get_text(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return nullptr;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return nullptr;
+ }
+
+ return strdup(static_cast<CGUIDialogProgressBarHandle*>(handle)->Text().c_str());
+}
+
+void Interface_GUIDialogExtendedProgress::set_text(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid handler data (handle='{}', "
+ "text='{}') on addon '{}'",
+ __func__, handle, static_cast<const void*>(text), addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->SetText(text);
+}
+
+bool Interface_GUIDialogExtendedProgress::is_finished(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return false;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return false;
+ }
+
+ return static_cast<CGUIDialogProgressBarHandle*>(handle)->IsFinished();
+}
+
+void Interface_GUIDialogExtendedProgress::mark_finished(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->MarkFinished();
+}
+
+float Interface_GUIDialogExtendedProgress::get_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return 0.0f;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return 0.0f;
+ }
+
+ return static_cast<CGUIDialogProgressBarHandle*>(handle)->Percentage();
+}
+
+void Interface_GUIDialogExtendedProgress::set_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ float percentage)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->SetPercentage(percentage);
+}
+
+void Interface_GUIDialogExtendedProgress::set_progress(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ int currentItem,
+ int itemCount)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogExtendedProgress::{} - invalid kodi base data",
+ __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogExtendedProgress::{} - invalid add-on data (handle='{}') on "
+ "addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgressBarHandle*>(handle)->SetProgress(currentItem, itemCount);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.h b/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.h
new file mode 100644
index 0000000..66ccb49
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/ExtendedProgressBar.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/extended_progress.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/ExtendedProgress.h"
+ */
+ struct Interface_GUIDialogExtendedProgress
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static KODI_GUI_HANDLE new_dialog(KODI_HANDLE kodiBase, const char* title);
+ static void delete_dialog(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static char* get_title(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void set_title(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, const char* title);
+ static char* get_text(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void set_text(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, const char* text);
+ static bool is_finished(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void mark_finished(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static float get_percentage(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void set_percentage(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, float percentage);
+ static void set_progress(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ int currentItem,
+ int itemCount);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/FileBrowser.cpp b/xbmc/addons/interfaces/gui/dialogs/FileBrowser.cpp
new file mode 100644
index 0000000..84d6443
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/FileBrowser.cpp
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "FileBrowser.h"
+
+#include "URL.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/FileBrowser.h"
+#include "dialogs/GUIDialogFileBrowser.h"
+#include "settings/MediaSourceSettings.h"
+#include "storage/MediaManager.h"
+#include "utils/URIUtils.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogFileBrowser::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser =
+ new AddonToKodiFuncTable_kodi_gui_dialogFileBrowser();
+
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_directory =
+ show_and_get_directory;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file = show_and_get_file;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file_from_dir =
+ show_and_get_file_from_dir;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file_list =
+ show_and_get_file_list;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_source = show_and_get_source;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_image = show_and_get_image;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_image_list =
+ show_and_get_image_list;
+ addonInterface->toKodi->kodi_gui->dialogFileBrowser->clear_file_list = clear_file_list;
+}
+
+void Interface_GUIDialogFileBrowser::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogFileBrowser;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_directory(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool write_only)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!shares || !heading || !path_in || !path_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
+ "heading='{}', path_in='{}', path_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
+ static_cast<const void*>(path_in), static_cast<void*>(path_out), addon->ID());
+ return false;
+ }
+
+ std::string strPath = path_in;
+
+ VECSOURCES vecShares;
+ GetVECShares(vecShares, shares, strPath);
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetDirectory(vecShares, heading, strPath, write_only);
+ if (bRet)
+ *path_out = strdup(strPath.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_file(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* mask,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool use_thumbs,
+ bool use_file_directories)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!shares || !mask || !heading || !path_in || !path_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', mask='{}', "
+ "heading='{}', path_in='{}', path_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(shares), static_cast<const void*>(mask),
+ static_cast<const void*>(heading), static_cast<const void*>(path_in),
+ static_cast<void*>(path_out), addon->ID());
+ return false;
+ }
+
+ std::string strPath = path_in;
+
+ VECSOURCES vecShares;
+ GetVECShares(vecShares, shares, strPath);
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetFile(vecShares, mask, heading, strPath, use_thumbs,
+ use_file_directories);
+ if (bRet)
+ *path_out = strdup(strPath.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_file_from_dir(KODI_HANDLE kodiBase,
+ const char* directory,
+ const char* mask,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool use_thumbs,
+ bool use_file_directories,
+ bool single_list)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!directory || !mask || !heading || !path_in || !path_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (directory='{}', "
+ "mask='{}', heading='{}', path_in='{}', path_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(directory), static_cast<const void*>(mask),
+ static_cast<const void*>(heading), static_cast<const void*>(path_in),
+ static_cast<void*>(path_out), addon->ID());
+ return false;
+ }
+
+ std::string strPath = path_in;
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetFile(directory, mask, heading, strPath, use_thumbs,
+ use_file_directories, single_list);
+ if (bRet)
+ *path_out = strdup(strPath.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_file_list(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* mask,
+ const char* heading,
+ char*** file_list,
+ unsigned int* entries,
+ bool use_thumbs,
+ bool use_file_directories)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!shares || !mask || !heading || !file_list || !entries)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', mask='{}', "
+ "heading='{}', file_list='{}', entries='{}') on addon '{}'",
+ __func__, static_cast<const void*>(shares), static_cast<const void*>(mask),
+ static_cast<const void*>(heading), static_cast<void*>(file_list),
+ static_cast<void*>(entries), addon->ID());
+ return false;
+ }
+
+ VECSOURCES vecShares;
+ GetVECShares(vecShares, shares, "");
+
+ std::vector<std::string> pathsInt;
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetFileList(vecShares, mask, heading, pathsInt,
+ use_thumbs, use_file_directories);
+ if (bRet)
+ {
+ *entries = pathsInt.size();
+ *file_list = static_cast<char**>(malloc(*entries * sizeof(char*)));
+ for (unsigned int i = 0; i < *entries; ++i)
+ (*file_list)[i] = strdup(pathsInt[i].c_str());
+ }
+ else
+ *entries = 0;
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_source(KODI_HANDLE kodiBase,
+ const char* path_in,
+ char** path_out,
+ bool allowNetworkShares,
+ const char* additionalShare,
+ const char* strType)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!strType || !additionalShare || !path_in || !path_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (additionalShare='{}', "
+ "strType='{}', path_in='{}', path_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(additionalShare),
+ static_cast<const void*>(strType), static_cast<const void*>(path_in),
+ static_cast<void*>(path_out), addon->ID());
+ return false;
+ }
+
+ std::string strPath = path_in;
+
+ VECSOURCES vecShares;
+ if (additionalShare)
+ GetVECShares(vecShares, additionalShare, strPath);
+ bool bRet =
+ CGUIDialogFileBrowser::ShowAndGetSource(strPath, allowNetworkShares, &vecShares, strType);
+ if (bRet)
+ *path_out = strdup(strPath.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_image(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ const char* path_in,
+ char** path_out)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!shares || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
+ "heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
+ addon->ID());
+ return false;
+ }
+
+ std::string strPath = path_in;
+
+ VECSOURCES vecShares;
+ GetVECShares(vecShares, shares, strPath);
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetImage(vecShares, heading, strPath);
+ if (bRet)
+ *path_out = strdup(strPath.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogFileBrowser::show_and_get_image_list(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ char*** file_list,
+ unsigned int* entries)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!shares || !heading || !file_list || !entries)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
+ "heading='{}', file_list='{}', entries='{}') on addon '{}'",
+ __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
+ static_cast<void*>(file_list), static_cast<void*>(entries), addon->ID());
+ return false;
+ }
+
+ VECSOURCES vecShares;
+ GetVECShares(vecShares, shares, "");
+
+ std::vector<std::string> pathsInt;
+ bool bRet = CGUIDialogFileBrowser::ShowAndGetImageList(vecShares, heading, pathsInt);
+ if (bRet)
+ {
+ *entries = pathsInt.size();
+ *file_list = static_cast<char**>(malloc(*entries * sizeof(char*)));
+ for (unsigned int i = 0; i < *entries; ++i)
+ (*file_list)[i] = strdup(pathsInt[i].c_str());
+ }
+ else
+ *entries = 0;
+ return bRet;
+}
+
+void Interface_GUIDialogFileBrowser::clear_file_list(KODI_HANDLE kodiBase,
+ char*** file_list,
+ unsigned int entries)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
+ return;
+ }
+
+ if (*file_list)
+ {
+ for (unsigned int i = 0; i < entries; ++i)
+ free((*file_list)[i]);
+ free(*file_list);
+ *file_list = nullptr;
+ }
+ else
+ {
+
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogFileBrowser::{} - invalid handler data (file_list='{}') on "
+ "addon '{}'",
+ __func__, static_cast<void*>(file_list), addon->ID());
+ }
+}
+
+void Interface_GUIDialogFileBrowser::GetVECShares(VECSOURCES& vecShares,
+ const std::string& strShares,
+ const std::string& strPath)
+{
+ std::size_t found;
+ found = strShares.find("local");
+ if (found != std::string::npos)
+ CServiceBroker::GetMediaManager().GetLocalDrives(vecShares);
+ found = strShares.find("network");
+ if (found != std::string::npos)
+ CServiceBroker::GetMediaManager().GetNetworkLocations(vecShares);
+ found = strShares.find("removable");
+ if (found != std::string::npos)
+ CServiceBroker::GetMediaManager().GetRemovableDrives(vecShares);
+ found = strShares.find("programs");
+ if (found != std::string::npos)
+ {
+ VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("programs");
+ if (sources != nullptr)
+ vecShares.insert(vecShares.end(), sources->begin(), sources->end());
+ }
+ found = strShares.find("files");
+ if (found != std::string::npos)
+ {
+ VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("files");
+ if (sources != nullptr)
+ vecShares.insert(vecShares.end(), sources->begin(), sources->end());
+ }
+ found = strShares.find("music");
+ if (found != std::string::npos)
+ {
+ VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("music");
+ if (sources != nullptr)
+ vecShares.insert(vecShares.end(), sources->begin(), sources->end());
+ }
+ found = strShares.find("video");
+ if (found != std::string::npos)
+ {
+ VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("video");
+ if (sources != nullptr)
+ vecShares.insert(vecShares.end(), sources->begin(), sources->end());
+ }
+ found = strShares.find("pictures");
+ if (found != std::string::npos)
+ {
+ VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("pictures");
+ if (sources != nullptr)
+ vecShares.insert(vecShares.end(), sources->begin(), sources->end());
+ }
+
+ if (vecShares.empty())
+ {
+ CMediaSource share;
+ std::string basePath = strPath;
+ std::string tempPath;
+ while (URIUtils::GetParentPath(basePath, tempPath))
+ basePath = tempPath;
+ share.strPath = basePath;
+ // don't include the user details in the share name
+ CURL url(share.strPath);
+ share.strName = url.GetWithoutUserDetails();
+ vecShares.push_back(share);
+ }
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/FileBrowser.h b/xbmc/addons/interfaces/gui/dialogs/FileBrowser.h
new file mode 100644
index 0000000..c2193f3
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/FileBrowser.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/filebrowser.h"
+
+#include <string>
+#include <vector>
+
+class CMediaSource;
+
+typedef std::vector<CMediaSource> VECSOURCES;
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/FileBrowser.h"
+ */
+ struct Interface_GUIDialogFileBrowser
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static bool show_and_get_directory(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool write_only);
+
+ static bool show_and_get_file(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* mask,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool use_thumbs,
+ bool use_file_directories);
+
+ static bool show_and_get_file_from_dir(KODI_HANDLE kodiBase,
+ const char* directory,
+ const char* mask,
+ const char* heading,
+ const char* path_in,
+ char** path_out,
+ bool use_thumbs,
+ bool use_file_directories,
+ bool singleList);
+
+ static bool show_and_get_file_list(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* mask,
+ const char* heading,
+ char*** file_list,
+ unsigned int* entries,
+ bool use_thumbs,
+ bool use_file_directories);
+
+ static bool show_and_get_source(KODI_HANDLE kodiBase,
+ const char* path_in,
+ char** path_out,
+ bool allow_network_shares,
+ const char* additional_share,
+ const char* type);
+
+ static bool show_and_get_image(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ const char* path_in,
+ char** path_out);
+
+ static bool show_and_get_image_list(KODI_HANDLE kodiBase,
+ const char* shares,
+ const char* heading,
+ char*** file_list,
+ unsigned int* entries);
+
+ static void clear_file_list(KODI_HANDLE kodiBase, char*** file_list, unsigned int entries);
+ //@}
+
+ private:
+ static void GetVECShares(VECSOURCES& vecShares,
+ const std::string& strShares,
+ const std::string& strPath);
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Keyboard.cpp b/xbmc/addons/interfaces/gui/dialogs/Keyboard.cpp
new file mode 100644
index 0000000..7ec56ab
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Keyboard.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Keyboard.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/Keyboard.h"
+#include "guilib/GUIKeyboardFactory.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogKeyboard::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogKeyboard =
+ new AddonToKodiFuncTable_kodi_gui_dialogKeyboard();
+
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_get_input_with_head =
+ show_and_get_input_with_head;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_get_input = show_and_get_input;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_get_new_password_with_head =
+ show_and_get_new_password_with_head;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_get_new_password =
+ show_and_get_new_password;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_verify_new_password_with_head =
+ show_and_verify_new_password_with_head;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_verify_new_password =
+ show_and_verify_new_password;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_verify_password =
+ show_and_verify_password;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->show_and_get_filter = show_and_get_filter;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->send_text_to_active_keyboard =
+ send_text_to_active_keyboard;
+ addonInterface->toKodi->kodi_gui->dialogKeyboard->is_keyboard_activated = is_keyboard_activated;
+}
+
+void Interface_GUIDialogKeyboard::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogKeyboard;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_get_input_with_head(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ const char* heading,
+ bool allow_empty_result,
+ bool hidden_input,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!text_in || !text_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (text_in='{}', "
+ "text_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(text_in), static_cast<void*>(text_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = text_in;
+ bool bRet = CGUIKeyboardFactory::ShowAndGetInput(str, CVariant{heading}, allow_empty_result,
+ hidden_input, auto_close_ms);
+ if (bRet)
+ *text_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_get_input(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ bool allow_empty_result,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!text_in || !text_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (text_in='{}', "
+ "text_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(text_in), static_cast<void*>(text_out),
+ addon->ID());
+ return false;
+ }
+
+ std::string str = text_in;
+ bool bRet = CGUIKeyboardFactory::ShowAndGetInput(str, allow_empty_result, auto_close_ms);
+ if (bRet)
+ *text_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_get_new_password_with_head(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ const char* heading,
+ bool allow_empty_result,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!password_in || !password_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (password_in='{}', "
+ "password_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(password_in), static_cast<void*>(password_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = password_in;
+ bool bRet =
+ CGUIKeyboardFactory::ShowAndGetNewPassword(str, heading, allow_empty_result, auto_close_ms);
+ if (bRet)
+ *password_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_get_new_password(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!password_in || !password_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (password_in='{}', "
+ "password_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(password_in), static_cast<void*>(password_out),
+ addon->ID());
+ return false;
+ }
+
+ std::string str = password_in;
+ bool bRet = CGUIKeyboardFactory::ShowAndGetNewPassword(str, auto_close_ms);
+ if (bRet)
+ *password_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_verify_new_password_with_head(KODI_HANDLE kodiBase,
+ char** password_out,
+ const char* heading,
+ bool allowEmpty,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!password_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (password_out='{}', "
+ "heading='{}') on addon '{}'",
+ __func__, static_cast<void*>(password_out), static_cast<const void*>(heading),
+ addon->ID());
+ return false;
+ }
+
+ std::string str;
+ bool bRet =
+ CGUIKeyboardFactory::ShowAndVerifyNewPassword(str, heading, allowEmpty, auto_close_ms);
+ if (bRet)
+ *password_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_verify_new_password(KODI_HANDLE kodiBase,
+ char** password_out,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!password_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (password_out='{}') on "
+ "addon '{}'",
+ __func__, static_cast<void*>(password_out), addon->ID());
+ return false;
+ }
+
+ std::string str;
+ bool bRet = CGUIKeyboardFactory::ShowAndVerifyNewPassword(str, auto_close_ms);
+ if (bRet)
+ *password_out = strdup(str.c_str());
+ return bRet;
+}
+
+int Interface_GUIDialogKeyboard::show_and_verify_password(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ const char* heading,
+ int retries,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!password_in || !password_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (password_in='{}', "
+ "password_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(password_in), static_cast<void*>(password_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = password_in;
+ int iRet = CGUIKeyboardFactory::ShowAndVerifyPassword(str, heading, retries, auto_close_ms);
+ if (iRet)
+ *password_out = strdup(str.c_str());
+ return iRet;
+}
+
+bool Interface_GUIDialogKeyboard::show_and_get_filter(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ bool searching,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!text_in || !text_out)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogKeyboard::{} - invalid handler data (text_in='{}', "
+ "text_out='{}') on addon '{}'",
+ __func__, static_cast<const void*>(text_in), static_cast<void*>(text_out),
+ addon->ID());
+ return false;
+ }
+
+
+ std::string str = text_in;
+ bool bRet = CGUIKeyboardFactory::ShowAndGetFilter(str, searching, auto_close_ms);
+ if (bRet)
+ *text_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogKeyboard::send_text_to_active_keyboard(KODI_HANDLE kodiBase,
+ const char* text,
+ bool close_keyboard)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ return CGUIKeyboardFactory::SendTextToActiveKeyboard(text, close_keyboard);
+}
+
+bool Interface_GUIDialogKeyboard::is_keyboard_activated(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogKeyboard::{} - invalid data", __func__);
+ return false;
+ }
+
+ return CGUIKeyboardFactory::isKeyboardActivated();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Keyboard.h b/xbmc/addons/interfaces/gui/dialogs/Keyboard.h
new file mode 100644
index 0000000..fb7d6b9
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Keyboard.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/keyboard.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/Keyboard.h"
+ */
+ struct Interface_GUIDialogKeyboard
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static bool show_and_get_input_with_head(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ const char* heading,
+ bool allow_empty_result,
+ bool hidden_input,
+ unsigned int auto_close_ms);
+ static bool show_and_get_input(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ bool allow_empty_result,
+ unsigned int auto_close_ms);
+ static bool show_and_get_new_password_with_head(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ const char* heading,
+ bool allow_empty_result,
+ unsigned int auto_close_ms);
+ static bool show_and_get_new_password(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ unsigned int auto_close_ms);
+ static bool show_and_verify_new_password_with_head(KODI_HANDLE kodiBase,
+ char** password_out,
+ const char* heading,
+ bool allowEmpty,
+ unsigned int auto_close_ms);
+ static bool show_and_verify_new_password(KODI_HANDLE kodiBase,
+ char** password_out,
+ unsigned int auto_close_ms);
+ static int show_and_verify_password(KODI_HANDLE kodiBase,
+ const char* password_in,
+ char** password_out,
+ const char* heading,
+ int retries,
+ unsigned int auto_close_ms);
+ static bool show_and_get_filter(KODI_HANDLE kodiBase,
+ const char* text_in,
+ char** text_out,
+ bool searching,
+ unsigned int auto_close_ms);
+ static bool send_text_to_active_keyboard(KODI_HANDLE kodiBase,
+ const char* text,
+ bool close_keyboard);
+ static bool is_keyboard_activated(KODI_HANDLE kodiBase);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Numeric.cpp b/xbmc/addons/interfaces/gui/dialogs/Numeric.cpp
new file mode 100644
index 0000000..a78aa4a
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Numeric.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Numeric.h"
+
+#include "XBDateTime.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/Numeric.h"
+#include "dialogs/GUIDialogNumeric.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogNumeric::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogNumeric =
+ new AddonToKodiFuncTable_kodi_gui_dialogNumeric();
+
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_verify_new_password =
+ show_and_verify_new_password;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_verify_password =
+ show_and_verify_password;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_verify_input = show_and_verify_input;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_get_time = show_and_get_time;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_get_date = show_and_get_date;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_get_ip_address =
+ show_and_get_ip_address;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_get_number = show_and_get_number;
+ addonInterface->toKodi->kodi_gui->dialogNumeric->show_and_get_seconds = show_and_get_seconds;
+}
+
+void Interface_GUIDialogNumeric::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogNumeric;
+}
+
+bool Interface_GUIDialogNumeric::show_and_verify_new_password(KODI_HANDLE kodiBase, char** password)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ std::string str;
+ bool bRet = CGUIDialogNumeric::ShowAndVerifyNewPassword(str);
+ if (bRet)
+ *password = strdup(str.c_str());
+ return bRet;
+}
+
+int Interface_GUIDialogNumeric::show_and_verify_password(KODI_HANDLE kodiBase,
+ const char* password,
+ const char* heading,
+ int retries)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return -1;
+ }
+
+ if (!password || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (password='{}', heading='{}') "
+ "on addon '{}'",
+ __func__, static_cast<const void*>(password), static_cast<const void*>(heading),
+ addon->ID());
+ return -1;
+ }
+
+ std::string pw(password);
+ return CGUIDialogNumeric::ShowAndVerifyPassword(pw, heading, retries);
+}
+
+bool Interface_GUIDialogNumeric::show_and_verify_input(KODI_HANDLE kodiBase,
+ const char* verify_in,
+ char** verify_out,
+ const char* heading,
+ bool verify_input)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!verify_in || !verify_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (verify_in='{}', "
+ "verify_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(verify_in), static_cast<void*>(verify_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = verify_in;
+ if (CGUIDialogNumeric::ShowAndVerifyInput(str, heading, verify_input) ==
+ InputVerificationResult::SUCCESS)
+ {
+ *verify_out = strdup(str.c_str());
+ return true;
+ }
+ return false;
+}
+
+bool Interface_GUIDialogNumeric::show_and_get_time(KODI_HANDLE kodiBase,
+ tm* time,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!time || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (time='{}', heading='{}') on "
+ "addon '{}'",
+ __func__, static_cast<void*>(time), static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ KODI::TIME::SystemTime systemTime;
+ CDateTime dateTime(*time);
+ dateTime.GetAsSystemTime(systemTime);
+ if (CGUIDialogNumeric::ShowAndGetTime(systemTime, heading))
+ {
+ dateTime = systemTime;
+ dateTime.GetAsTm(*time);
+ return true;
+ }
+ return false;
+}
+
+bool Interface_GUIDialogNumeric::show_and_get_date(KODI_HANDLE kodiBase,
+ tm* date,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!date || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (date='{}', heading='{}') on "
+ "addon '{}'",
+ __func__, static_cast<void*>(date), static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ KODI::TIME::SystemTime systemTime;
+ CDateTime dateTime(*date);
+ dateTime.GetAsSystemTime(systemTime);
+ if (CGUIDialogNumeric::ShowAndGetDate(systemTime, heading))
+ {
+ dateTime = systemTime;
+ dateTime.GetAsTm(*date);
+ return true;
+ }
+ return false;
+}
+
+bool Interface_GUIDialogNumeric::show_and_get_ip_address(KODI_HANDLE kodiBase,
+ const char* ip_address_in,
+ char** ip_address_out,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!ip_address_in || !ip_address_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (ip_address_in='{}', "
+ "ip_address_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(ip_address_in), static_cast<void*>(ip_address_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string strIP = ip_address_in;
+ bool bRet = CGUIDialogNumeric::ShowAndGetIPAddress(strIP, heading);
+ if (bRet)
+ *ip_address_out = strdup(strIP.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogNumeric::show_and_get_number(KODI_HANDLE kodiBase,
+ const char* number_in,
+ char** number_out,
+ const char* heading,
+ unsigned int auto_close_ms)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!number_in || !number_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (number_in='{}', "
+ "number_out='{}', heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(number_in), static_cast<void*>(number_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = number_in;
+ bool bRet = CGUIDialogNumeric::ShowAndGetNumber(str, heading, auto_close_ms);
+ if (bRet)
+ *number_out = strdup(str.c_str());
+ return bRet;
+}
+
+bool Interface_GUIDialogNumeric::show_and_get_seconds(KODI_HANDLE kodiBase,
+ const char* time_in,
+ char** time_out,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogNumeric::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!time_in || !time_out || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogNumeric::{} - invalid handler data (time_in='{}', time_out='{}', "
+ "heading='{}') on addon '{}'",
+ __func__, static_cast<const void*>(time_in), static_cast<void*>(time_out),
+ static_cast<const void*>(heading), addon->ID());
+ return false;
+ }
+
+ std::string str = time_in;
+ bool bRet = CGUIDialogNumeric::ShowAndGetSeconds(str, heading);
+ if (bRet)
+ *time_out = strdup(str.c_str());
+ return bRet;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Numeric.h b/xbmc/addons/interfaces/gui/dialogs/Numeric.h
new file mode 100644
index 0000000..a54ad52
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Numeric.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/numeric.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/Numeric.h"
+ */
+ struct Interface_GUIDialogNumeric
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static bool show_and_verify_new_password(KODI_HANDLE kodiBase, char** password);
+ static int show_and_verify_password(KODI_HANDLE kodiBase,
+ const char* password,
+ const char* heading,
+ int retries);
+ static bool show_and_verify_input(KODI_HANDLE kodiBase,
+ const char* verify_in,
+ char** verify_out,
+ const char* heading,
+ bool verify_input);
+ static bool show_and_get_time(KODI_HANDLE kodiBase, tm* time, const char* heading);
+ static bool show_and_get_date(KODI_HANDLE kodiBase, tm* date, const char* heading);
+ static bool show_and_get_ip_address(KODI_HANDLE kodiBase,
+ const char* ip_address_in,
+ char** ip_address_out,
+ const char* heading);
+ static bool show_and_get_number(KODI_HANDLE kodiBase,
+ const char* number_in,
+ char** number_out,
+ const char* heading,
+ unsigned int auto_close_ms);
+ static bool show_and_get_seconds(KODI_HANDLE kodiBase,
+ const char* time_in,
+ char** time_out,
+ const char* heading);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/OK.cpp b/xbmc/addons/interfaces/gui/dialogs/OK.cpp
new file mode 100644
index 0000000..90e9d69
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/OK.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "OK.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/OK.h"
+#include "messaging/helpers/DialogOKHelper.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+using namespace KODI::MESSAGING;
+
+namespace ADDON
+{
+
+void Interface_GUIDialogOK::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogOK = new AddonToKodiFuncTable_kodi_gui_dialogOK();
+
+ addonInterface->toKodi->kodi_gui->dialogOK->show_and_get_input_single_text =
+ show_and_get_input_single_text;
+ addonInterface->toKodi->kodi_gui->dialogOK->show_and_get_input_line_text =
+ show_and_get_input_line_text;
+}
+
+void Interface_GUIDialogOK::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogOK;
+}
+
+void Interface_GUIDialogOK::show_and_get_input_single_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon || !heading || !text)
+ {
+ CLog::Log(
+ LOGERROR, "Interface_GUIDialogOK:{} - invalid data (addon='{}', heading='{}', text='{}')",
+ __func__, kodiBase, static_cast<const void*>(heading), static_cast<const void*>(text));
+ return;
+ }
+
+ HELPERS::ShowOKDialogText(CVariant{heading}, CVariant{text});
+}
+
+void Interface_GUIDialogOK::show_and_get_input_line_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon || !heading || !line0 || !line1 || !line2)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogOK::{} - invalid data (addon='{}', heading='{}', line0='{}', "
+ "line1='{}', line2='{}')",
+ __func__, kodiBase, static_cast<const void*>(heading),
+ static_cast<const void*>(line0), static_cast<const void*>(line1),
+ static_cast<const void*>(line2));
+ return;
+ }
+ HELPERS::ShowOKDialogLines(CVariant{heading}, CVariant{line0}, CVariant{line1}, CVariant{line2});
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/OK.h b/xbmc/addons/interfaces/gui/dialogs/OK.h
new file mode 100644
index 0000000..fd13719
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/OK.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/ok.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/OK.h"
+ */
+ struct Interface_GUIDialogOK
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note For add of new functions use the "_" style to identify direct a
+ * add-on callback function. Everything with CamelCase is only for the
+ * usage in Kodi only.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void show_and_get_input_single_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* text);
+ static void show_and_get_input_line_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Progress.cpp b/xbmc/addons/interfaces/gui/dialogs/Progress.cpp
new file mode 100644
index 0000000..ff6c742
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Progress.cpp
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2015-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Progress.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/Progress.h"
+#include "dialogs/GUIDialogProgress.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogProgress::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogProgress =
+ new AddonToKodiFuncTable_kodi_gui_dialogProgress();
+
+ addonInterface->toKodi->kodi_gui->dialogProgress->new_dialog = new_dialog;
+ addonInterface->toKodi->kodi_gui->dialogProgress->delete_dialog = delete_dialog;
+ addonInterface->toKodi->kodi_gui->dialogProgress->open = open;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_heading = set_heading;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_line = set_line;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_can_cancel = set_can_cancel;
+ addonInterface->toKodi->kodi_gui->dialogProgress->is_canceled = is_canceled;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_percentage = set_percentage;
+ addonInterface->toKodi->kodi_gui->dialogProgress->get_percentage = get_percentage;
+ addonInterface->toKodi->kodi_gui->dialogProgress->show_progress_bar = show_progress_bar;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_progress_max = set_progress_max;
+ addonInterface->toKodi->kodi_gui->dialogProgress->set_progress_advance = set_progress_advance;
+ addonInterface->toKodi->kodi_gui->dialogProgress->abort = abort;
+}
+
+void Interface_GUIDialogProgress::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogProgress;
+}
+
+KODI_GUI_HANDLE Interface_GUIDialogProgress::new_dialog(KODI_HANDLE kodiBase)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return nullptr;
+ }
+
+ CGUIDialogProgress* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogProgress>(
+ WINDOW_DIALOG_PROGRESS);
+ if (!dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (dialog='{}') on addon '{}'",
+ __func__, static_cast<void*>(dialog), addon->ID());
+ return nullptr;
+ }
+
+ return dialog;
+}
+
+void Interface_GUIDialogProgress::delete_dialog(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->Close();
+}
+
+void Interface_GUIDialogProgress::open(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->Open();
+}
+
+void Interface_GUIDialogProgress::set_heading(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ const char* heading)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle || !heading)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}', heading='{}') "
+ "on addon '{}'",
+ __func__, handle, static_cast<const void*>(heading), addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetHeading(heading);
+}
+
+void Interface_GUIDialogProgress::set_line(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ unsigned int line,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle || !text)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}', text='{}') on "
+ "addon '{}'",
+ __func__, handle, static_cast<const void*>(text), addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetLine(line, text);
+}
+
+void Interface_GUIDialogProgress::set_can_cancel(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ bool canCancel)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetCanCancel(canCancel);
+}
+
+bool Interface_GUIDialogProgress::is_canceled(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return false;
+ }
+
+ return static_cast<CGUIDialogProgress*>(handle)->IsCanceled();
+}
+
+void Interface_GUIDialogProgress::set_percentage(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ int percentage)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetPercentage(percentage);
+}
+
+int Interface_GUIDialogProgress::get_percentage(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return 0;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return 0;
+ }
+
+ return static_cast<CGUIDialogProgress*>(handle)->GetPercentage();
+}
+
+void Interface_GUIDialogProgress::show_progress_bar(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ bool onOff)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->ShowProgressBar(onOff);
+}
+
+void Interface_GUIDialogProgress::set_progress_max(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ int max)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetProgressMax(max);
+}
+
+void Interface_GUIDialogProgress::set_progress_advance(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ int nSteps)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return;
+ }
+
+ static_cast<CGUIDialogProgress*>(handle)->SetProgressAdvance(nSteps);
+}
+
+bool Interface_GUIDialogProgress::abort(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogProgress::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!handle)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogProgress::{} - invalid handler data (handle='{}') on addon '{}'",
+ __func__, handle, addon->ID());
+ return false;
+ }
+
+ return static_cast<CGUIDialogProgress*>(handle)->Abort();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Progress.h b/xbmc/addons/interfaces/gui/dialogs/Progress.h
new file mode 100644
index 0000000..ba31f3c
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Progress.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/progress.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/Progress.h"
+ */
+ struct Interface_GUIDialogProgress
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static KODI_GUI_HANDLE new_dialog(KODI_HANDLE kodiBase);
+ static void delete_dialog(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void open(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void set_heading(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, const char* heading);
+ static void set_line(KODI_HANDLE kodiBase,
+ KODI_GUI_HANDLE handle,
+ unsigned int line,
+ const char* text);
+ static void set_can_cancel(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, bool canCancel);
+ static bool is_canceled(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void set_percentage(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, int percentage);
+ static int get_percentage(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ static void show_progress_bar(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, bool bOnOff);
+ static void set_progress_max(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, int max);
+ static void set_progress_advance(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle, int nSteps);
+ static bool abort(KODI_HANDLE kodiBase, KODI_GUI_HANDLE handle);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Select.cpp b/xbmc/addons/interfaces/gui/dialogs/Select.cpp
new file mode 100644
index 0000000..7ad6ed6
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Select.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "Select.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/Select.h"
+#include "dialogs/GUIDialogSelect.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogSelect::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogSelect = new AddonToKodiFuncTable_kodi_gui_dialogSelect();
+
+ addonInterface->toKodi->kodi_gui->dialogSelect->open = open;
+ addonInterface->toKodi->kodi_gui->dialogSelect->open_multi_select = open_multi_select;
+}
+
+void Interface_GUIDialogSelect::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogSelect;
+}
+
+int Interface_GUIDialogSelect::open(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entries[],
+ unsigned int size,
+ int selected,
+ unsigned int autoclose)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogSelect::{} - invalid data", __func__);
+ return -1;
+ }
+
+ CGUIDialogSelect* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(
+ WINDOW_DIALOG_SELECT);
+ if (!heading || !entries || !dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogSelect::{} - invalid handler data (heading='{}', entries='{}', "
+ "dialog='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(entries),
+ static_cast<void*>(dialog), addon->ID());
+ return -1;
+ }
+
+ dialog->Reset();
+ dialog->SetHeading(CVariant{heading});
+
+ for (unsigned int i = 0; i < size; ++i)
+ dialog->Add(entries[i]);
+
+ if (selected > 0)
+ dialog->SetSelected(selected);
+ if (autoclose > 0)
+ dialog->SetAutoClose(autoclose);
+
+ dialog->Open();
+ return dialog->GetSelectedItem();
+}
+
+
+bool Interface_GUIDialogSelect::open_multi_select(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entryIDs[],
+ const char* entryNames[],
+ bool entriesSelected[],
+ unsigned int size,
+ unsigned int autoclose)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogMultiSelect::{} - invalid data", __func__);
+ return false;
+ }
+
+ CGUIDialogSelect* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(
+ WINDOW_DIALOG_SELECT);
+ if (!heading || !entryIDs || !entryNames || !entriesSelected || !dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogMultiSelect::{} - invalid handler data (heading='{}', "
+ "entryIDs='{}', entryNames='{}', entriesSelected='{}', dialog='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(entryIDs),
+ static_cast<const void*>(entryNames), static_cast<void*>(entriesSelected),
+ static_cast<void*>(dialog), addon->ID());
+ return false;
+ }
+
+ dialog->Reset();
+ dialog->SetMultiSelection(true);
+ dialog->SetHeading(CVariant{heading});
+
+ std::vector<int> selectedIndexes;
+
+ for (unsigned int i = 0; i < size; ++i)
+ {
+ dialog->Add(entryNames[i]);
+ if (entriesSelected[i])
+ selectedIndexes.push_back(i);
+ }
+
+ dialog->SetSelected(selectedIndexes);
+ if (autoclose > 0)
+ dialog->SetAutoClose(autoclose);
+
+ dialog->Open();
+ if (dialog->IsConfirmed())
+ {
+ for (unsigned int i = 0; i < size; ++i)
+ entriesSelected[i] = false;
+
+ selectedIndexes = dialog->GetSelectedItems();
+
+ for (unsigned int i = 0; i < selectedIndexes.size(); ++i)
+ {
+ if (selectedIndexes[i])
+ entriesSelected[selectedIndexes[i]] = true;
+ }
+ }
+
+ return true;
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/Select.h b/xbmc/addons/interfaces/gui/dialogs/Select.h
new file mode 100644
index 0000000..5f2d0ef
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/Select.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/select.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/Select.h"
+ */
+ struct Interface_GUIDialogSelect
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static int open(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entries[],
+ unsigned int size,
+ int selected,
+ unsigned int autoclose);
+ static bool open_multi_select(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* entryIDs[],
+ const char* entryNames[],
+ bool entriesSelected[],
+ unsigned int size,
+ unsigned int autoclose);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/TextViewer.cpp b/xbmc/addons/interfaces/gui/dialogs/TextViewer.cpp
new file mode 100644
index 0000000..637975a
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/TextViewer.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "TextViewer.h"
+
+#include "ServiceBroker.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/TextViewer.h"
+#include "dialogs/GUIDialogTextViewer.h"
+#include "guilib/GUIComponent.h"
+#include "guilib/GUIWindowManager.h"
+#include "utils/log.h"
+
+namespace ADDON
+{
+
+void Interface_GUIDialogTextViewer::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogTextViewer =
+ new AddonToKodiFuncTable_kodi_gui_dialogTextViewer();
+
+ addonInterface->toKodi->kodi_gui->dialogTextViewer->open = open;
+}
+
+void Interface_GUIDialogTextViewer::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogTextViewer;
+}
+
+void Interface_GUIDialogTextViewer::open(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* text)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogTextViewer::{} - invalid data", __func__);
+ return;
+ }
+
+ CGUIDialogTextViewer* dialog =
+ CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogTextViewer>(
+ WINDOW_DIALOG_TEXT_VIEWER);
+ if (!heading || !text || !dialog)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogTextViewer::{} - invalid handler data (heading='{}', text='{}', "
+ "dialog='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(text),
+ static_cast<void*>(dialog), addon->ID());
+ return;
+ }
+
+ dialog->SetHeading(heading);
+ dialog->SetText(text);
+ dialog->Open();
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/TextViewer.h b/xbmc/addons/interfaces/gui/dialogs/TextViewer.h
new file mode 100644
index 0000000..873dbbb
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/TextViewer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/text_viewer.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/TextViewer.h"
+ */
+ struct Interface_GUIDialogTextViewer
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static void open(KODI_HANDLE kodiBase, const char* heading, const char* text);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp b/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp
new file mode 100644
index 0000000..89dea58
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/YesNo.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "YesNo.h"
+
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/kodi-dev-kit/include/kodi/gui/dialogs/YesNo.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "messaging/helpers/DialogHelper.h"
+#include "utils/log.h"
+
+using namespace KODI::MESSAGING;
+using KODI::MESSAGING::HELPERS::DialogResponse;
+
+namespace ADDON
+{
+
+void Interface_GUIDialogYesNo::Init(AddonGlobalInterface* addonInterface)
+{
+ addonInterface->toKodi->kodi_gui->dialogYesNo = new AddonToKodiFuncTable_kodi_gui_dialogYesNo();
+
+ addonInterface->toKodi->kodi_gui->dialogYesNo->show_and_get_input_single_text =
+ show_and_get_input_single_text;
+ addonInterface->toKodi->kodi_gui->dialogYesNo->show_and_get_input_line_text =
+ show_and_get_input_line_text;
+ addonInterface->toKodi->kodi_gui->dialogYesNo->show_and_get_input_line_button_text =
+ show_and_get_input_line_button_text;
+}
+
+void Interface_GUIDialogYesNo::DeInit(AddonGlobalInterface* addonInterface)
+{
+ delete addonInterface->toKodi->kodi_gui->dialogYesNo;
+}
+
+bool Interface_GUIDialogYesNo::show_and_get_input_single_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* text,
+ bool* canceled,
+ const char* noLabel,
+ const char* yesLabel)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogYesNo::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!heading || !text || !canceled || !noLabel || !yesLabel)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogYesNo::{} - invalid handler data (heading='{}', text='{}', "
+ "canceled='{}', noLabel='{}', yesLabel='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(text),
+ static_cast<void*>(canceled), static_cast<const void*>(noLabel),
+ static_cast<const void*>(yesLabel), addon->ID());
+ return false;
+ }
+
+ DialogResponse result = HELPERS::ShowYesNoDialogText(heading, text, noLabel, yesLabel);
+ *canceled = (result == DialogResponse::CHOICE_CANCELLED);
+ return (result == DialogResponse::CHOICE_YES);
+}
+
+bool Interface_GUIDialogYesNo::show_and_get_input_line_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2,
+ const char* noLabel,
+ const char* yesLabel)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogYesNo::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!heading || !line0 || !line1 || !line2 || !noLabel || !yesLabel)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogYesNo::{} - invalid handler data (heading='{}', line0='{}', "
+ "line1='{}', line2='{}', "
+ "noLabel='{}', yesLabel='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(line0),
+ static_cast<const void*>(line1), static_cast<const void*>(line2),
+ static_cast<const void*>(noLabel), static_cast<const void*>(yesLabel), addon->ID());
+ return false;
+ }
+
+ return HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel) ==
+ DialogResponse::CHOICE_YES;
+}
+
+bool Interface_GUIDialogYesNo::show_and_get_input_line_button_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2,
+ bool* canceled,
+ const char* noLabel,
+ const char* yesLabel)
+{
+ CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
+ if (!addon)
+ {
+ CLog::Log(LOGERROR, "Interface_GUIDialogYesNo::{} - invalid data", __func__);
+ return false;
+ }
+
+ if (!heading || !line0 || !line1 || !line2 || !canceled || !noLabel || !yesLabel)
+ {
+ CLog::Log(LOGERROR,
+ "Interface_GUIDialogYesNo::{} - invalid handler data (heading='{}', line0='{}', "
+ "line1='{}', line2='{}', "
+ "canceled='{}', noLabel='{}', yesLabel='{}') on addon '{}'",
+ __func__, static_cast<const void*>(heading), static_cast<const void*>(line0),
+ static_cast<const void*>(line1), static_cast<const void*>(line2),
+ static_cast<const void*>(canceled), static_cast<const void*>(noLabel),
+ static_cast<const void*>(yesLabel), addon->ID());
+ return false;
+ }
+
+ DialogResponse result =
+ HELPERS::ShowYesNoDialogLines(heading, line0, line1, line2, noLabel, yesLabel);
+ *canceled = (result == DialogResponse::CHOICE_CANCELLED);
+ return (result == DialogResponse::CHOICE_YES);
+}
+
+} /* namespace ADDON */
diff --git a/xbmc/addons/interfaces/gui/dialogs/YesNo.h b/xbmc/addons/interfaces/gui/dialogs/YesNo.h
new file mode 100644
index 0000000..84e5d73
--- /dev/null
+++ b/xbmc/addons/interfaces/gui/dialogs/YesNo.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include "addons/kodi-dev-kit/include/kodi/c-api/gui/dialogs/yes_no.h"
+
+extern "C"
+{
+
+ struct AddonGlobalInterface;
+
+ namespace ADDON
+ {
+
+ /*!
+ * @brief Global gui Add-on to Kodi callback functions
+ *
+ * To hold functions not related to a instance type and usable for
+ * every add-on type.
+ *
+ * Related add-on header is "./xbmc/addons/kodi-dev-kit/include/kodi/gui/dialogs/YesNo.h"
+ */
+ struct Interface_GUIDialogYesNo
+ {
+ static void Init(AddonGlobalInterface* addonInterface);
+ static void DeInit(AddonGlobalInterface* addonInterface);
+
+ /*!
+ * @brief callback functions from add-on to kodi
+ *
+ * @note To add a new function use the "_" style to directly identify an
+ * add-on callback function. Everything with CamelCase is only to be used
+ * in Kodi.
+ *
+ * The parameter `kodiBase` is used to become the pointer for a `CAddonDll`
+ * class.
+ */
+ //@{
+ static bool show_and_get_input_single_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* text,
+ bool* canceled,
+ const char* noLabel,
+ const char* yesLabel);
+
+ static bool show_and_get_input_line_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2,
+ const char* noLabel,
+ const char* yesLabel);
+
+ static bool show_and_get_input_line_button_text(KODI_HANDLE kodiBase,
+ const char* heading,
+ const char* line0,
+ const char* line1,
+ const char* line2,
+ bool* canceled,
+ const char* noLabel,
+ const char* yesLabel);
+ //@}
+ };
+
+ } /* namespace ADDON */
+} /* extern "C" */
diff --git a/xbmc/addons/interfaces/platform/android/System.cpp b/xbmc/addons/interfaces/platform/android/System.cpp
new file mode 100644
index 0000000..9f83b22
--- /dev/null
+++ b/xbmc/addons/interfaces/platform/android/System.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "System.h"
+
+#include "CompileInfo.h"
+#include "addons/binary-addons/AddonDll.h"
+#include "addons/interfaces/AddonBase.h"
+#include "addons/kodi-dev-kit/include/kodi/platform/android/System.h"
+
+#include "platform/android/activity/XBMCApp.h"
+
+static AddonToKodiFuncTable_android_system function_table;
+
+namespace ADDON
+{
+
+void Interface_Android::Register()
+{
+ function_table.get_jni_env = get_jni_env;
+ function_table.get_sdk_version = get_sdk_version;
+ function_table.get_class_name = get_class_name;
+ Interface_Base::RegisterInterface(Get);
+}
+
+void* Interface_Android::Get(const std::string &name, const std::string &version)
+{
+ if (name == INTERFACE_ANDROID_SYSTEM_NAME
+ && version >= INTERFACE_ANDROID_SYSTEM_VERSION_MIN
+ && version <= INTERFACE_ANDROID_SYSTEM_VERSION)
+ return &function_table;
+
+ return nullptr;
+};
+
+void* Interface_Android::get_jni_env()
+{
+ return xbmc_jnienv();
+}
+
+int Interface_Android::get_sdk_version()
+{
+ return CXBMCApp::Get().GetSDKVersion();
+}
+
+const char *Interface_Android::get_class_name()
+{
+ return CCompileInfo::GetClass();
+}
+
+
+} //namespace ADDON
diff --git a/xbmc/addons/interfaces/platform/android/System.h b/xbmc/addons/interfaces/platform/android/System.h
new file mode 100644
index 0000000..59805ab
--- /dev/null
+++ b/xbmc/addons/interfaces/platform/android/System.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+namespace ADDON
+{
+
+struct Interface_Android
+{
+ static void Register();
+ static void* Get(const std::string &name, const std::string &version);
+
+ static void* get_jni_env();
+ static int get_sdk_version();
+ static const char *get_class_name();
+};
+
+} //namespace ADDON