summaryrefslogtreecommitdiffstats
path: root/xbmc/games/controllers/windows/GUIControllerList.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/games/controllers/windows/GUIControllerList.cpp')
-rw-r--r--xbmc/games/controllers/windows/GUIControllerList.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/xbmc/games/controllers/windows/GUIControllerList.cpp b/xbmc/games/controllers/windows/GUIControllerList.cpp
new file mode 100644
index 0000000..02f8d37
--- /dev/null
+++ b/xbmc/games/controllers/windows/GUIControllerList.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2014-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 "GUIControllerList.h"
+
+#include "GUIControllerDefines.h"
+#include "GUIControllerWindow.h"
+#include "GUIFeatureList.h"
+#include "ServiceBroker.h"
+#include "addons/AddonManager.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "games/GameServices.h"
+#include "games/addons/GameClient.h"
+#include "games/addons/input/GameClientInput.h"
+#include "games/controllers/Controller.h"
+#include "games/controllers/ControllerIDs.h"
+#include "games/controllers/ControllerLayout.h"
+#include "games/controllers/guicontrols/GUIControllerButton.h"
+#include "games/controllers/guicontrols/GUIGameController.h"
+#include "games/controllers/types/ControllerTree.h"
+#include "guilib/GUIButtonControl.h"
+#include "guilib/GUIControlGroupList.h"
+#include "guilib/GUIMessage.h"
+#include "guilib/GUIWindow.h"
+#include "messaging/ApplicationMessenger.h"
+#include "peripherals/Peripherals.h"
+#include "utils/StringUtils.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <iterator>
+
+using namespace KODI;
+using namespace ADDON;
+using namespace GAME;
+
+CGUIControllerList::CGUIControllerList(CGUIWindow* window,
+ IFeatureList* featureList,
+ GameClientPtr gameClient)
+ : m_guiWindow(window),
+ m_featureList(featureList),
+ m_controllerList(nullptr),
+ m_controllerButton(nullptr),
+ m_focusedController(-1), // Initially unfocused
+ m_gameClient(std::move(gameClient))
+{
+ assert(m_featureList != nullptr);
+}
+
+bool CGUIControllerList::Initialize(void)
+{
+ m_controllerList =
+ dynamic_cast<CGUIControlGroupList*>(m_guiWindow->GetControl(CONTROL_CONTROLLER_LIST));
+ m_controllerButton =
+ dynamic_cast<CGUIButtonControl*>(m_guiWindow->GetControl(CONTROL_CONTROLLER_BUTTON_TEMPLATE));
+
+ if (m_controllerButton)
+ m_controllerButton->SetVisible(false);
+
+ CServiceBroker::GetAddonMgr().Events().Subscribe(this, &CGUIControllerList::OnEvent);
+ Refresh("");
+
+ return m_controllerList != nullptr && m_controllerButton != nullptr;
+}
+
+void CGUIControllerList::Deinitialize(void)
+{
+ CServiceBroker::GetAddonMgr().Events().Unsubscribe(this);
+
+ CleanupButtons();
+
+ m_controllerList = nullptr;
+ m_controllerButton = nullptr;
+}
+
+bool CGUIControllerList::Refresh(const std::string& controllerId)
+{
+ // Focus specified controller after refresh
+ std::string focusController = controllerId;
+
+ if (focusController.empty() && m_focusedController >= 0)
+ {
+ // If controller ID wasn't provided, focus current controller
+ focusController = m_controllers[m_focusedController]->ID();
+ }
+
+ if (!RefreshControllers())
+ return false;
+
+ CleanupButtons();
+
+ if (m_controllerList)
+ {
+ unsigned int buttonId = 0;
+ for (const auto& controller : m_controllers)
+ {
+ CGUIButtonControl* pButton =
+ new CGUIControllerButton(*m_controllerButton, controller->Layout().Label(), buttonId++);
+ m_controllerList->AddControl(pButton);
+
+ if (!focusController.empty() && controller->ID() == focusController)
+ {
+ CGUIMessage msg(GUI_MSG_SETFOCUS, m_guiWindow->GetID(), pButton->GetID());
+ m_guiWindow->OnMessage(msg);
+ }
+
+ // Just in case
+ if (buttonId >= MAX_CONTROLLER_COUNT)
+ break;
+ }
+ }
+
+ return true;
+}
+
+void CGUIControllerList::OnFocus(unsigned int controllerIndex)
+{
+ if (controllerIndex < m_controllers.size())
+ {
+ m_focusedController = controllerIndex;
+
+ const ControllerPtr& controller = m_controllers[controllerIndex];
+ m_featureList->Load(controller);
+
+ //! @todo Activate controller for all game controller controls
+ CGUIGameController* pController =
+ dynamic_cast<CGUIGameController*>(m_guiWindow->GetControl(CONTROL_GAME_CONTROLLER));
+ if (pController)
+ pController->ActivateController(controller);
+
+ // Update controller description
+ CGUIMessage msg(GUI_MSG_LABEL_SET, m_guiWindow->GetID(), CONTROL_CONTROLLER_DESCRIPTION);
+ msg.SetLabel(controller->Description());
+ m_guiWindow->OnMessage(msg);
+ }
+}
+
+void CGUIControllerList::OnSelect(unsigned int controllerIndex)
+{
+ m_featureList->OnSelect(0);
+}
+
+void CGUIControllerList::ResetController(void)
+{
+ if (0 <= m_focusedController && m_focusedController < (int)m_controllers.size())
+ {
+ const std::string strControllerId = m_controllers[m_focusedController]->ID();
+
+ //! @todo Choose peripheral
+ // For now, ask the user if they would like to reset all peripherals
+ // "Reset controller profile"
+ // "Would you like to reset this controller profile for all devices?"
+ if (!CGUIDialogYesNo::ShowAndGetInput(35060, 35061))
+ return;
+
+ CServiceBroker::GetPeripherals().ResetButtonMaps(strControllerId);
+ }
+}
+
+void CGUIControllerList::OnEvent(const ADDON::AddonEvent& event)
+{
+ if (typeid(event) == typeid(ADDON::AddonEvents::Enabled) || // also called on install,
+ typeid(event) == typeid(ADDON::AddonEvents::Disabled) || // not called on uninstall
+ typeid(event) == typeid(ADDON::AddonEvents::ReInstalled) ||
+ typeid(event) == typeid(ADDON::AddonEvents::UnInstalled))
+ {
+ CGUIMessage msg(GUI_MSG_REFRESH_LIST, m_guiWindow->GetID(), CONTROL_CONTROLLER_LIST);
+
+ // Focus installed add-on
+ if (typeid(event) == typeid(ADDON::AddonEvents::Enabled) ||
+ typeid(event) == typeid(ADDON::AddonEvents::ReInstalled))
+ msg.SetStringParam(event.addonId);
+
+ CServiceBroker::GetAppMessenger()->SendGUIMessage(msg, m_guiWindow->GetID());
+ }
+}
+
+bool CGUIControllerList::RefreshControllers(void)
+{
+ // Get current controllers
+ CGameServices& gameServices = CServiceBroker::GetGameServices();
+ ControllerVector newControllers = gameServices.GetControllers();
+
+ // Filter by current game add-on
+ if (m_gameClient)
+ {
+ const CControllerTree& controllers = m_gameClient->Input().GetDefaultControllerTree();
+
+ auto ControllerNotAccepted = [&controllers](const ControllerPtr& controller) {
+ return !controllers.IsControllerAccepted(controller->ID());
+ };
+
+ if (!std::all_of(newControllers.begin(), newControllers.end(), ControllerNotAccepted))
+ newControllers.erase(
+ std::remove_if(newControllers.begin(), newControllers.end(), ControllerNotAccepted),
+ newControllers.end());
+ }
+
+ // Check for changes
+ std::set<std::string> oldControllerIds;
+ std::set<std::string> newControllerIds;
+
+ auto GetControllerID = [](const ControllerPtr& controller) { return controller->ID(); };
+
+ std::transform(m_controllers.begin(), m_controllers.end(),
+ std::inserter(oldControllerIds, oldControllerIds.begin()), GetControllerID);
+ std::transform(newControllers.begin(), newControllers.end(),
+ std::inserter(newControllerIds, newControllerIds.begin()), GetControllerID);
+
+ const bool bChanged = (oldControllerIds != newControllerIds);
+ if (bChanged)
+ {
+ m_controllers = std::move(newControllers);
+
+ // Sort add-ons, with default controller first
+ std::sort(m_controllers.begin(), m_controllers.end(),
+ [](const ControllerPtr& i, const ControllerPtr& j) {
+ if (i->ID() == DEFAULT_CONTROLLER_ID && j->ID() != DEFAULT_CONTROLLER_ID)
+ return true;
+ if (i->ID() != DEFAULT_CONTROLLER_ID && j->ID() == DEFAULT_CONTROLLER_ID)
+ return false;
+
+ return StringUtils::CompareNoCase(i->Layout().Label(), j->Layout().Label()) < 0;
+ });
+ }
+
+ return bChanged;
+}
+
+void CGUIControllerList::CleanupButtons(void)
+{
+ if (m_controllerList)
+ m_controllerList->ClearAll();
+}