aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Brown <themagnificentmrb@gmail.com>2021-10-16 17:18:32 -0700
committerGarrett Brown <themagnificentmrb@gmail.com>2021-11-09 07:22:29 -0800
commit7b347ded65975cb72e42cfe147601de9c0d196ab (patch)
treef96c638bda89291d45eb1c7a934f0b3ace4bf674
parent4dc197a915aaf9fc98e8db3186f80b52012dd728 (diff)
Controllers: Refactor ControllerTree.h classes into new files
-rw-r--r--xbmc/games/controllers/types/CMakeLists.txt7
-rw-r--r--xbmc/games/controllers/types/ControllerHub.cpp108
-rw-r--r--xbmc/games/controllers/types/ControllerHub.h53
-rw-r--r--xbmc/games/controllers/types/ControllerNode.cpp125
-rw-r--r--xbmc/games/controllers/types/ControllerNode.h106
-rw-r--r--xbmc/games/controllers/types/ControllerTree.cpp321
-rw-r--r--xbmc/games/controllers/types/ControllerTree.h228
-rw-r--r--xbmc/games/controllers/types/PortNode.cpp137
-rw-r--r--xbmc/games/controllers/types/PortNode.h120
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