diff options
-rw-r--r-- | xbmc/games/controllers/types/CMakeLists.txt | 7 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerHub.cpp | 108 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerHub.h | 53 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerNode.cpp | 125 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerNode.h | 106 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerTree.cpp | 321 | ||||
-rw-r--r-- | xbmc/games/controllers/types/ControllerTree.h | 228 | ||||
-rw-r--r-- | xbmc/games/controllers/types/PortNode.cpp | 137 | ||||
-rw-r--r-- | xbmc/games/controllers/types/PortNode.h | 120 |
9 files changed, 664 insertions, 541 deletions
diff --git a/xbmc/games/controllers/types/CMakeLists.txt b/xbmc/games/controllers/types/CMakeLists.txt index 24dfed9044..fc9d6c89e0 100644 --- a/xbmc/games/controllers/types/CMakeLists.txt +++ b/xbmc/games/controllers/types/CMakeLists.txt @@ -1,9 +1,14 @@ set(SOURCES ControllerGrid.cpp - ControllerTree.cpp + ControllerHub.cpp + ControllerNode.cpp + PortNode.cpp ) set(HEADERS ControllerGrid.h + ControllerHub.h + ControllerNode.h ControllerTree.h + PortNode.h ) core_add_library(games_controller_types) diff --git a/xbmc/games/controllers/types/ControllerHub.cpp b/xbmc/games/controllers/types/ControllerHub.cpp new file mode 100644 index 0000000000..c2245d0e66 --- /dev/null +++ b/xbmc/games/controllers/types/ControllerHub.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017-2021 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 "ControllerHub.h" + +#include "ControllerTree.h" +#include "games/controllers/Controller.h" + +#include <algorithm> +#include <utility> + +using namespace KODI; +using namespace GAME; + +CControllerHub::~CControllerHub() = default; + +CControllerHub& CControllerHub::operator=(const CControllerHub& rhs) +{ + if (this != &rhs) + { + m_ports = rhs.m_ports; + } + + return *this; +} + +CControllerHub& CControllerHub::operator=(CControllerHub&& rhs) +{ + if (this != &rhs) + { + m_ports = std::move(rhs.m_ports); + } + + return *this; +} + +void CControllerHub::Clear() +{ + m_ports.clear(); +} + +void CControllerHub::SetPorts(PortVec ports) +{ + m_ports = std::move(ports); +} + +bool CControllerHub::IsControllerAccepted(const std::string& controllerId) const +{ + return std::any_of(m_ports.begin(), m_ports.end(), [controllerId](const CPortNode& port) { + return port.IsControllerAccepted(controllerId); + }); +} + +bool CControllerHub::IsControllerAccepted(const std::string& portAddress, + const std::string& controllerId) const +{ + return std::any_of(m_ports.begin(), m_ports.end(), + [portAddress, controllerId](const CPortNode& port) { + return port.IsControllerAccepted(portAddress, controllerId); + }); +} + +ControllerVector CControllerHub::GetControllers() const +{ + ControllerVector controllers; + GetControllers(controllers); + return controllers; +} + +void CControllerHub::GetControllers(ControllerVector& controllers) const +{ + for (const CPortNode& port : m_ports) + { + for (const CControllerNode& node : port.CompatibleControllers()) + node.GetControllers(controllers); + } +} + +const CPortNode& CControllerHub::GetPort(const std::string& address) const +{ + return GetPort(m_ports, address); +} + +const CPortNode& CControllerHub::GetPort(const PortVec& ports, const std::string& address) +{ + for (const CPortNode& port : ports) + { + if (port.Address() == address) + return port; + + for (const CControllerNode& controller : port.CompatibleControllers()) + { + for (const CPortNode& controllerPort : controller.Hub().Ports()) + { + if (port.Address() == address) + return controllerPort; + } + } + } + + static const CPortNode empty{}; + return empty; +} diff --git a/xbmc/games/controllers/types/ControllerHub.h b/xbmc/games/controllers/types/ControllerHub.h new file mode 100644 index 0000000000..c4294e3cd9 --- /dev/null +++ b/xbmc/games/controllers/types/ControllerHub.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017-2021 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 "PortNode.h" +#include "games/controllers/ControllerTypes.h" + +#include <string> + +namespace KODI +{ +namespace GAME +{ +/*! + * \brief A branch in the controller tree + */ +class CControllerHub +{ +public: + CControllerHub() = default; + CControllerHub(const CControllerHub& other) { *this = other; } + CControllerHub(CControllerHub&& other) = default; + CControllerHub& operator=(const CControllerHub& rhs); + CControllerHub& operator=(CControllerHub&& rhs); + ~CControllerHub(); + + void Clear(); + + bool HasPorts() const { return !m_ports.empty(); } + PortVec& Ports() { return m_ports; } + const PortVec& Ports() const { return m_ports; } + void SetPorts(PortVec ports); + + bool IsControllerAccepted(const std::string& controllerId) const; + bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; + ControllerVector GetControllers() const; + void GetControllers(ControllerVector& controllers) const; + + const CPortNode& GetPort(const std::string& address) const; + +private: + static const CPortNode& GetPort(const PortVec& ports, const std::string& address); + + PortVec m_ports; +}; +} // namespace GAME +} // namespace KODI diff --git a/xbmc/games/controllers/types/ControllerNode.cpp b/xbmc/games/controllers/types/ControllerNode.cpp new file mode 100644 index 0000000000..50530d2642 --- /dev/null +++ b/xbmc/games/controllers/types/ControllerNode.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2017-2021 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 "ControllerNode.h" + +#include "ControllerHub.h" +#include "PortNode.h" +#include "games/controllers/Controller.h" +#include "games/controllers/ControllerTopology.h" + +#include <algorithm> +#include <utility> + +using namespace KODI; +using namespace GAME; + +CControllerNode::CControllerNode() : m_hub(new CControllerHub) +{ +} + +CControllerNode::~CControllerNode() = default; + +CControllerNode& CControllerNode::operator=(const CControllerNode& rhs) +{ + if (this != &rhs) + { + m_controller = rhs.m_controller; + m_address = rhs.m_address; + m_hub.reset(new CControllerHub(*rhs.m_hub)); + } + + return *this; +} + +CControllerNode& CControllerNode::operator=(CControllerNode&& rhs) +{ + if (this != &rhs) + { + m_controller = std::move(rhs.m_controller); + m_address = std::move(rhs.m_address); + m_hub = std::move(rhs.m_hub); + } + + return *this; +} + +void CControllerNode::Clear() +{ + m_controller.reset(); + m_address.clear(); + m_hub.reset(new CControllerHub); +} + +void CControllerNode::SetController(ControllerPtr controller) +{ + m_controller = std::move(controller); +} + +void CControllerNode::GetControllers(ControllerVector& controllers) const +{ + const ControllerPtr& myController = m_controller; + + auto it = std::find_if(controllers.begin(), controllers.end(), + [&myController](const ControllerPtr& controller) { + return myController->ID() == controller->ID(); + }); + + if (it == controllers.end()) + controllers.emplace_back(m_controller); + + m_hub->GetControllers(controllers); +} + +void CControllerNode::SetAddress(std::string address) +{ + m_address = std::move(address); +} + +void CControllerNode::SetHub(CControllerHub hub) +{ + m_hub.reset(new CControllerHub(std::move(hub))); +} + +bool CControllerNode::IsControllerAccepted(const std::string& controllerId) const +{ + bool bAccepted = false; + + for (const auto& port : m_hub->Ports()) + { + if (port.IsControllerAccepted(controllerId)) + { + bAccepted = true; + break; + } + } + + return bAccepted; +} + +bool CControllerNode::IsControllerAccepted(const std::string& portAddress, + const std::string& controllerId) const +{ + bool bAccepted = false; + + for (const auto& port : m_hub->Ports()) + { + if (port.IsControllerAccepted(portAddress, controllerId)) + { + bAccepted = true; + break; + } + } + + return bAccepted; +} + +bool CControllerNode::ProvidesInput() const +{ + return m_controller && m_controller->Topology().ProvidesInput(); +} diff --git a/xbmc/games/controllers/types/ControllerNode.h b/xbmc/games/controllers/types/ControllerNode.h new file mode 100644 index 0000000000..e9590e63a6 --- /dev/null +++ b/xbmc/games/controllers/types/ControllerNode.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2017-2021 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 "games/controllers/ControllerTypes.h" + +#include <memory> +#include <string> +#include <vector> + +namespace KODI +{ +namespace GAME +{ +class CControllerHub; + +/*! + * \brief Node in the controller tree + * + * The node identifies the controller profile, and optionally the available + * controller ports. + */ +class CControllerNode +{ +public: + CControllerNode(); + CControllerNode(const CControllerNode& other) { *this = other; } + CControllerNode(CControllerNode&& other) = default; + CControllerNode& operator=(const CControllerNode& rhs); + CControllerNode& operator=(CControllerNode&& rhs); + ~CControllerNode(); + + void Clear(); + + /*! + * \brief Controller profile of this code + * + * \return Controller profile, or empty if this node is invalid + * + * \sa IsValid() + */ + const ControllerPtr& Controller() const { return m_controller; } + void SetController(ControllerPtr controller); + + void GetControllers(ControllerVector& controllers) const; + + /*! + * \brief Address given to the node by the implementation + */ + const std::string& Address() const { return m_address; } + void SetAddress(std::string address); + + /*! + * \brief Collection of ports on this controller + * + * \return A hub with controller ports, or an empty hub if this controller + * has no available ports + */ + const CControllerHub& Hub() const { return *m_hub; } + CControllerHub& Hub() { return *m_hub; } + void SetHub(CControllerHub hub); + + /*! + * \brief Check if this node has a valid controller profile + */ + bool IsValid() const { return static_cast<bool>(m_controller); } + + /*! + * \brief Check to see if a controller is compatible with a controller port + * + * \param controllerId The ID of the controller + * + * \return True if the controller is compatible with a port, false otherwise + */ + bool IsControllerAccepted(const std::string& controllerId) const; + + /*! + * \brief Check to see if a controller is compatible with a controller port + * + * \param portAddress The port address + * \param controllerId The ID of the controller + * + * \return True if the controller is compatible with a port, false otherwise + */ + bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; + + /*! + * \brief Check if this node provides input + */ + bool ProvidesInput() const; + +private: + ControllerPtr m_controller; + std::string m_address; + std::unique_ptr<CControllerHub> m_hub; +}; + +using ControllerNodeVec = std::vector<CControllerNode>; +} // namespace GAME +} // namespace KODI diff --git a/xbmc/games/controllers/types/ControllerTree.cpp b/xbmc/games/controllers/types/ControllerTree.cpp deleted file mode 100644 index 2e9b037936..0000000000 --- a/xbmc/games/controllers/types/ControllerTree.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (C) 2017-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 "ControllerTree.h" - -#include "games/controllers/Controller.h" -#include "games/controllers/ControllerTopology.h" - -#include <algorithm> -#include <utility> - -using namespace KODI; -using namespace GAME; - -// --- CControllerNode --------------------------------------------------------- - -CControllerNode::CControllerNode() : m_hub(new CControllerHub) -{ -} - -CControllerNode::~CControllerNode() = default; - -CControllerNode& CControllerNode::operator=(const CControllerNode& rhs) -{ - if (this != &rhs) - { - m_controller = rhs.m_controller; - m_address = rhs.m_address; - m_hub.reset(new CControllerHub(*rhs.m_hub)); - } - - return *this; -} - -void CControllerNode::Clear() -{ - m_controller.reset(); - m_address.clear(); - m_hub.reset(new CControllerHub); -} - -void CControllerNode::SetController(ControllerPtr controller) -{ - m_controller = std::move(controller); -} - -void CControllerNode::GetControllers(ControllerVector& controllers) const -{ - const ControllerPtr& myController = m_controller; - - auto it = std::find_if(controllers.begin(), controllers.end(), - [&myController](const ControllerPtr& controller) { - return myController->ID() == controller->ID(); - }); - - if (it == controllers.end()) - controllers.emplace_back(m_controller); - - m_hub->GetControllers(controllers); -} - -void CControllerNode::SetAddress(std::string address) -{ - m_address = std::move(address); -} - -void CControllerNode::SetHub(CControllerHub hub) -{ - m_hub.reset(new CControllerHub(std::move(hub))); -} - -bool CControllerNode::IsControllerAccepted(const std::string& controllerId) const -{ - bool bAccepted = false; - - for (const auto& port : m_hub->Ports()) - { - if (port.IsControllerAccepted(controllerId)) - { - bAccepted = true; - break; - } - } - - return bAccepted; -} - -bool CControllerNode::IsControllerAccepted(const std::string& portAddress, - const std::string& controllerId) const -{ - bool bAccepted = false; - - for (const auto& port : m_hub->Ports()) - { - if (port.IsControllerAccepted(portAddress, controllerId)) - { - bAccepted = true; - break; - } - } - - return bAccepted; -} - -bool CControllerNode::ProvidesInput() const -{ - return m_controller && m_controller->Topology().ProvidesInput(); -} - -// --- CPortNode --------------------------------------------------------------- - -CPortNode::~CPortNode() = default; - -CPortNode& CPortNode::operator=(const CPortNode& rhs) -{ - if (this != &rhs) - { - m_bConnected = rhs.m_bConnected; - m_portType = rhs.m_portType; - m_portId = rhs.m_portId; - m_controllers = rhs.m_controllers; - m_address = rhs.m_address; - m_active = rhs.m_active; - } - - return *this; -} - -const CControllerNode& CPortNode::ActiveController() const -{ - if (m_bConnected && m_active < m_controllers.size()) - return m_controllers[m_active]; - - static const CControllerNode invalid{}; - return invalid; -} - -CControllerNode& CPortNode::ActiveController() -{ - if (m_bConnected && m_active < m_controllers.size()) - return m_controllers[m_active]; - - static CControllerNode invalid; - invalid.Clear(); - return invalid; -} - -void CPortNode::SetPortID(std::string portId) -{ - m_portId = std::move(portId); -} - -void CPortNode::SetAddress(std::string address) -{ - m_address = std::move(address); -} - -void CPortNode::SetCompatibleControllers(ControllerNodeVec controllers) -{ - m_controllers = std::move(controllers); -} - -bool CPortNode::IsControllerAccepted(const std::string& controllerId) const -{ - // Base case - CControllerPort port; - GetControllerPort(port); - if (port.IsCompatible(controllerId)) - return true; - - // Visit nodes - for (const auto& node : m_controllers) - { - if (node.IsControllerAccepted(controllerId)) - return true; - } - - return false; -} - -bool CPortNode::IsControllerAccepted(const std::string& portAddress, - const std::string& controllerId) const -{ - bool bAccepted = false; - - if (m_address == portAddress) - { - // Base case - CControllerPort port; - GetControllerPort(port); - if (port.IsCompatible(controllerId)) - bAccepted = true; - } - else - { - // Visit nodes - for (const auto& node : m_controllers) - { - if (node.IsControllerAccepted(portAddress, controllerId)) - { - bAccepted = true; - break; - } - } - } - - return bAccepted; -} - -void CPortNode::GetControllerPort(CControllerPort& port) const -{ - std::vector<std::string> accepts; - for (const CControllerNode& node : m_controllers) - accepts.emplace_back(node.Controller()->ID()); - - port = CControllerPort(m_portId, std::move(accepts)); -} - -// --- CControllerHub ---------------------------------------------------------- - -CControllerHub::~CControllerHub() = default; - -CControllerHub& CControllerHub::operator=(const CControllerHub& rhs) -{ - if (this != &rhs) - { - m_ports = rhs.m_ports; - } - - return *this; -} - -void CControllerHub::Clear() -{ - m_ports.clear(); -} - -void CControllerHub::SetPorts(PortVec ports) -{ - m_ports = std::move(ports); -} - -bool CControllerHub::IsControllerAccepted(const std::string& controllerId) const -{ - bool bAccepted = false; - - for (const CPortNode& port : m_ports) - { - if (port.IsControllerAccepted(controllerId)) - { - bAccepted = true; - break; - } - } - - return bAccepted; -} - -bool CControllerHub::IsControllerAccepted(const std::string& portAddress, - const std::string& controllerId) const -{ - bool bAccepted = false; - - for (const CPortNode& port : m_ports) - { - if (port.IsControllerAccepted(portAddress, controllerId)) - { - bAccepted = true; - break; - } - } - - return bAccepted; -} - -ControllerVector CControllerHub::GetControllers() const -{ - ControllerVector controllers; - GetControllers(controllers); - return controllers; -} - -void CControllerHub::GetControllers(ControllerVector& controllers) const -{ - for (const CPortNode& port : m_ports) - { - for (const CControllerNode& node : port.CompatibleControllers()) - node.GetControllers(controllers); - } -} - -const CPortNode& CControllerHub::GetPort(const std::string& address) const -{ - return GetPort(m_ports, address); -} - -const CPortNode& CControllerHub::GetPort(const PortVec& ports, const std::string& address) -{ - for (const CPortNode& port : ports) - { - if (port.Address() == address) - return port; - - for (const CControllerNode& controller : port.CompatibleControllers()) - { - for (const CPortNode& controllerPort : controller.Hub().Ports()) - { - if (port.Address() == address) - return controllerPort; - } - } - } - - static const CPortNode empty{}; - return empty; -} diff --git a/xbmc/games/controllers/types/ControllerTree.h b/xbmc/games/controllers/types/ControllerTree.h index d1cb0f8a5d..47e42e9faf 100644 --- a/xbmc/games/controllers/types/ControllerTree.h +++ b/xbmc/games/controllers/types/ControllerTree.h @@ -8,230 +8,20 @@ #pragma once -#include "games/controllers/ControllerTypes.h" - -#include <map> -#include <memory> -#include <string> -#include <vector> +// +// Note: Hierarchy of headers is: +// +// - ControllerTree.h (this file) +// - ControllerHub.h +// - PortNode.h +// - ControllerNode.h +// +#include "ControllerHub.h" namespace KODI { namespace GAME { -class CControllerHub; -class CControllerPort; - -/*! - * \brief Node in the controller tree - * - * The node identifies the controller profile, and optionally the available - * controller ports. - */ -class CControllerNode -{ -public: - CControllerNode(); - CControllerNode(const CControllerNode& other) { *this = other; } - CControllerNode(CControllerNode&& other) = default; - CControllerNode& operator=(const CControllerNode& rhs); - ~CControllerNode(); - - void Clear(); - - /*! - * \brief Controller profile of this code - * - * \return Controller profile, or empty if this node is invalid - * - * \sa IsValid() - */ - const ControllerPtr& Controller() const { return m_controller; } - void SetController(ControllerPtr controller); - - void GetControllers(ControllerVector& controllers) const; - - /*! - * \brief Address given to the node by the implementation - */ - const std::string& Address() const { return m_address; } - void SetAddress(std::string address); - - /*! - * \brief Collection of ports on this controller - * - * \return A hub with controller ports, or an empty hub if this controller - * has no available ports - */ - const CControllerHub& Hub() const { return *m_hub; } - CControllerHub& Hub() { return *m_hub; } - void SetHub(CControllerHub hub); - - /*! - * \brief Check if this node has a valid controller profile - */ - bool IsValid() const { return m_controller.get() != nullptr; } - - /*! - * \brief Check to see if a controller is compatible with a controller port - * - * \param controllerId The ID of the controller - * - * \return True if the controller is compatible with a port, false otherwise - */ - bool IsControllerAccepted(const std::string& controllerId) const; - - /*! - * \brief Check to see if a controller is compatible with a controller port - * - * \param portAddress The port address - * \param controllerId The ID of the controller - * - * \return True if the controller is compatible with a port, false otherwise - */ - bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; - - /*! - * \brief Check if this node provides input - */ - bool ProvidesInput() const; - -private: - ControllerPtr m_controller; - std::string m_address; - std::unique_ptr<CControllerHub> m_hub; -}; - -using ControllerNodeVec = std::vector<CControllerNode>; - -/*! - * \brief Collection of nodes that can be connected to this port - */ -class CPortNode -{ -public: - CPortNode() = default; - CPortNode(const CPortNode& other) { *this = other; } - CPortNode(CPortNode&& other) = default; - CPortNode& operator=(const CPortNode& rhs); - ~CPortNode(); - - /*! - * \brief Connection state of the port - * - * \return True if a controller is connected, false otherwise - */ - bool Connected() const { return m_bConnected; } - void SetConnected(bool bConnected) { m_bConnected = bConnected; } - - /*! - * \brief The controller that is active on this port - * - * \return The active controller, or invalid if port is disconnected - */ - const CControllerNode& ActiveController() const; - CControllerNode& ActiveController(); - void SetActiveController(unsigned int controllerIndex) { m_active = controllerIndex; } - - /*! - * \brief The port type - * - * \return The port type, if known - */ - PORT_TYPE PortType() const { return m_portType; } - void SetPortType(PORT_TYPE type) { m_portType = type; } - - /*! - * \brief The hardware or controller port ID - * - * \return The port ID of the hardware port or controller port, or empty if - * the port is only identified by its type - */ - const std::string& PortID() const { return m_portId; } - void SetPortID(std::string portId); - - /*! - * \brief Address given to the node by the implementation - */ - const std::string& Address() const { return m_address; } - void SetAddress(std::string address); - - /*! - * \brief Return the controller profiles that are compatible with this port - * - * \return The controller profiles, or empty if this port doesn't support - * any controller profiles - */ - const ControllerNodeVec& CompatibleControllers() const { return m_controllers; } - void SetCompatibleControllers(ControllerNodeVec controllers); - - /*! - * \brief Check to see if a controller is compatible with this tree - * - * \param controllerId The ID of the controller - * - * \return True if the controller is compatible with the tree, false otherwise - */ - bool IsControllerAccepted(const std::string& controllerId) const; - - /*! - * \brief Check to see if a controller is compatible with this tree - * - * \param portAddress The port address - * \param controllerId The ID of the controller - * - * \return True if the controller is compatible with the tree, false otherwise - */ - bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; - -private: - void GetControllerPort(CControllerPort& port) const; - - bool m_bConnected = false; - unsigned int m_active = 0; - PORT_TYPE m_portType = PORT_TYPE::UNKNOWN; - std::string m_portId; - std::string m_address; - ControllerNodeVec m_controllers; -}; - -/*! - * \brief Collection of port nodes - */ -using PortVec = std::vector<CPortNode>; - -/*! - * \brief A branch in the controller tree - */ -class CControllerHub -{ -public: - CControllerHub() = default; - CControllerHub(const CControllerHub& other) { *this = other; } - CControllerHub(CControllerHub&& other) = default; - CControllerHub& operator=(const CControllerHub& rhs); - ~CControllerHub(); - - void Clear(); - - bool HasPorts() const { return !m_ports.empty(); } - PortVec& Ports() { return m_ports; } - const PortVec& Ports() const { return m_ports; } - void SetPorts(PortVec ports); - - bool IsControllerAccepted(const std::string& controllerId) const; - bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; - ControllerVector GetControllers() const; - void GetControllers(ControllerVector& controllers) const; - - const CPortNode& GetPort(const std::string& address) const; - -private: - static const CPortNode& GetPort(const PortVec& ports, const std::string& address); - - PortVec m_ports; -}; - /*! * \brief Collection of ports on a console */ diff --git a/xbmc/games/controllers/types/PortNode.cpp b/xbmc/games/controllers/types/PortNode.cpp new file mode 100644 index 0000000000..b3df64764d --- /dev/null +++ b/xbmc/games/controllers/types/PortNode.cpp @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2017-2021 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 "PortNode.h" + +#include "games/controllers/Controller.h" +#include "games/controllers/ControllerPort.h" +#include "games/controllers/types/ControllerHub.h" + +#include <algorithm> +#include <utility> + +using namespace KODI; +using namespace GAME; + +CPortNode::~CPortNode() = default; + +CPortNode& CPortNode::operator=(const CPortNode& rhs) +{ + if (this != &rhs) + { + m_bConnected = rhs.m_bConnected; + m_portType = rhs.m_portType; + m_portId = rhs.m_portId; + m_controllers = rhs.m_controllers; + m_address = rhs.m_address; + m_active = rhs.m_active; + } + + return *this; +} + +CPortNode& CPortNode::operator=(CPortNode&& rhs) +{ + if (this != &rhs) + { + m_bConnected = rhs.m_bConnected; + m_active = rhs.m_active; + m_portType = rhs.m_portType; + m_portId = std::move(rhs.m_portId); + m_address = std::move(rhs.m_address); + m_controllers = std::move(rhs.m_controllers); + } + + return *this; +} + +const CControllerNode& CPortNode::ActiveController() const +{ + if (m_bConnected && m_active < m_controllers.size()) + return m_controllers[m_active]; + + static const CControllerNode invalid{}; + return invalid; +} + +CControllerNode& CPortNode::ActiveController() +{ + if (m_bConnected && m_active < m_controllers.size()) + return m_controllers[m_active]; + + static CControllerNode invalid; + invalid.Clear(); + return invalid; +} + +void CPortNode::SetPortID(std::string portId) +{ + m_portId = std::move(portId); +} + +void CPortNode::SetAddress(std::string address) +{ + m_address = std::move(address); +} + +void CPortNode::SetCompatibleControllers(ControllerNodeVec controllers) +{ + m_controllers = std::move(controllers); +} + +bool CPortNode::IsControllerAccepted(const std::string& controllerId) const +{ + // Base case + CControllerPort port; + GetPort(port); + if (port.IsCompatible(controllerId)) + return true; + + // Visit nodes + return std::any_of(m_controllers.begin(), m_controllers.end(), + [controllerId](const CControllerNode& node) { + return node.IsControllerAccepted(controllerId); + }); +} + +bool CPortNode::IsControllerAccepted(const std::string& portAddress, + const std::string& controllerId) const +{ + bool bAccepted = false; + + if (m_address == portAddress) + { + // Base case + CControllerPort port; + GetPort(port); + if (port.IsCompatible(controllerId)) + bAccepted = true; + } + else + { + // Visit nodes + if (std::any_of(m_controllers.begin(), m_controllers.end(), + [portAddress, controllerId](const CControllerNode& node) { + return node.IsControllerAccepted(portAddress, controllerId); + })) + { + bAccepted = true; + } + } + + return bAccepted; +} + +void CPortNode::GetPort(CControllerPort& port) const +{ + std::vector<std::string> accepts; + for (const CControllerNode& node : m_controllers) + accepts.emplace_back(node.Controller()->ID()); + + port = CControllerPort(m_portId, std::move(accepts)); +} diff --git a/xbmc/games/controllers/types/PortNode.h b/xbmc/games/controllers/types/PortNode.h new file mode 100644 index 0000000000..7104c7b9e4 --- /dev/null +++ b/xbmc/games/controllers/types/PortNode.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017-2021 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 "ControllerNode.h" +#include "games/controllers/ControllerTypes.h" + +#include <string> +#include <vector> + +namespace KODI +{ +namespace GAME +{ +class CControllerPort; + +/*! + * \brief Collection of nodes that can be connected to this port + */ +class CPortNode +{ +public: + CPortNode() = default; + CPortNode(const CPortNode& other) { *this = other; } + CPortNode(CPortNode&& other) = default; + CPortNode& operator=(const CPortNode& rhs); + CPortNode& operator=(CPortNode&& rhs); + ~CPortNode(); + + /*! + * \brief Connection state of the port + * + * \return True if a controller is connected, false otherwise + */ + bool Connected() const { return m_bConnected; } + void SetConnected(bool bConnected) { m_bConnected = bConnected; } + + /*! + * \brief The controller that is active on this port + * + * \return The active controller, or invalid if port is disconnected + */ + const CControllerNode& ActiveController() const; + CControllerNode& ActiveController(); + void SetActiveController(unsigned int controllerIndex) { m_active = controllerIndex; } + + /*! + * \brief The port type + * + * \return The port type, if known + */ + PORT_TYPE PortType() const { return m_portType; } + void SetPortType(PORT_TYPE type) { m_portType = type; } + + /*! + * \brief The hardware or controller port ID + * + * \return The port ID of the hardware port or controller port, or empty if + * the port is only identified by its type + */ + const std::string& PortID() const { return m_portId; } + void SetPortID(std::string portId); + + /*! + * \brief Address given to the node by the implementation + */ + const std::string& Address() const { return m_address; } + void SetAddress(std::string address); + + /*! + * \brief Return the controller profiles that are compatible with this port + * + * \return The controller profiles, or empty if this port doesn't support + * any controller profiles + */ + const ControllerNodeVec& CompatibleControllers() const { return m_controllers; } + void SetCompatibleControllers(ControllerNodeVec controllers); + + /*! + * \brief Check to see if a controller is compatible with this tree + * + * \param controllerId The ID of the controller + * + * \return True if the controller is compatible with the tree, false otherwise + */ + bool IsControllerAccepted(const std::string& controllerId) const; + + /*! + * \brief Check to see if a controller is compatible with this tree + * + * \param portAddress The port address + * \param controllerId The ID of the controller + * + * \return True if the controller is compatible with the tree, false otherwise + */ + bool IsControllerAccepted(const std::string& portAddress, const std::string& controllerId) const; + +private: + void GetPort(CControllerPort& port) const; + + bool m_bConnected = false; + unsigned int m_active = 0; + PORT_TYPE m_portType = PORT_TYPE::UNKNOWN; + std::string m_portId; + std::string m_address; + ControllerNodeVec m_controllers; +}; + +/*! + * \brief Collection of port nodes + */ +using PortVec = std::vector<CPortNode>; +} // namespace GAME +} // namespace KODI |