summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/interfaces/gui/Window.cpp
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/gui/Window.cpp
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/gui/Window.cpp')
-rw-r--r--xbmc/addons/interfaces/gui/Window.cpp1499
1 files changed, 1499 insertions, 0 deletions
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 */