summaryrefslogtreecommitdiffstats
path: root/xbmc/peripherals/devices/PeripheralJoystick.h
blob: aa55ad7fd75a8be81311c4728d09654b64bec298 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 *  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.
 */

#pragma once

#include "Peripheral.h"
#include "XBDateTime.h"
#include "games/controllers/ControllerTypes.h"
#include "input/joysticks/JoystickTypes.h"
#include "input/joysticks/interfaces/IDriverReceiver.h"
#include "threads/CriticalSection.h"

#include <future>
#include <memory>
#include <queue>
#include <string>
#include <vector>

#define JOYSTICK_PORT_UNKNOWN (-1)

namespace KODI
{
namespace JOYSTICK
{
class CDeadzoneFilter;
class CKeymapHandling;
class CRumbleGenerator;
class IButtonMap;
class IDriverHandler;
class IInputHandler;
} // namespace JOYSTICK
} // namespace KODI

namespace PERIPHERALS
{
class CPeripherals;

class CPeripheralJoystick : public CPeripheral, //! @todo extend CPeripheralHID
                            public KODI::JOYSTICK::IDriverReceiver
{
public:
  CPeripheralJoystick(CPeripherals& manager,
                      const PeripheralScanResult& scanResult,
                      CPeripheralBus* bus);

  ~CPeripheralJoystick(void) override;

  // implementation of CPeripheral
  bool InitialiseFeature(const PeripheralFeature feature) override;
  void OnUserNotification() override;
  bool TestFeature(PeripheralFeature feature) override;
  void RegisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler,
                                     bool bPromiscuous) override;
  void UnregisterJoystickDriverHandler(KODI::JOYSTICK::IDriverHandler* handler) override;
  KODI::JOYSTICK::IDriverReceiver* GetDriverReceiver() override { return this; }
  IKeymap* GetKeymap(const std::string& controllerId) override;
  CDateTime LastActive() override { return m_lastActive; }
  KODI::GAME::ControllerPtr ControllerProfile() const override;
  void SetControllerProfile(const KODI::GAME::ControllerPtr& controller) override;

  bool OnButtonMotion(unsigned int buttonIndex, bool bPressed);
  bool OnHatMotion(unsigned int hatIndex, KODI::JOYSTICK::HAT_STATE state);
  bool OnAxisMotion(unsigned int axisIndex, float position);
  void OnInputFrame(void);

  // implementation of IDriverReceiver
  bool SetMotorState(unsigned int motorIndex, float magnitude) override;

  /*!
   * \brief Get the name of the driver or API providing this joystick
   */
  const std::string& Provider(void) const { return m_strProvider; }

  /*!
   * \brief Get the specific port number requested by this joystick
   *
   * This could indicate that the joystick is connected to a hardware port
   * with a number label; some controllers, such as the Xbox 360 controller,
   * also have LEDs that indicate the controller is on a specific port.
   *
   * \return The 0-indexed port number, or JOYSTICK_PORT_UNKNOWN if no port is requested
   */
  int RequestedPort(void) const { return m_requestedPort; }

  /*!
   * \brief Get the number of elements reported by the driver
   */
  unsigned int ButtonCount(void) const { return m_buttonCount; }
  unsigned int HatCount(void) const { return m_hatCount; }
  unsigned int AxisCount(void) const { return m_axisCount; }
  unsigned int MotorCount(void) const { return m_motorCount; }
  bool SupportsPowerOff(void) const { return m_supportsPowerOff; }

  /*!
   * \brief Set joystick properties
   */
  void SetProvider(const std::string& provider) { m_strProvider = provider; }
  void SetRequestedPort(int port) { m_requestedPort = port; }
  void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; }
  void SetHatCount(unsigned int hatCount) { m_hatCount = hatCount; }
  void SetAxisCount(unsigned int axisCount) { m_axisCount = axisCount; }
  void SetMotorCount(unsigned int motorCount); // specialized to update m_features
  void SetSupportsPowerOff(bool bSupportsPowerOff); // specialized to update m_features

protected:
  void InitializeDeadzoneFiltering(KODI::JOYSTICK::IButtonMap& buttonMap);
  void InitializeControllerProfile(KODI::JOYSTICK::IButtonMap& buttonMap);

  void PowerOff();

  // Helper functions
  KODI::GAME::ControllerPtr InstallAsync(const std::string& controllerId);
  static bool InstallSync(const std::string& controllerId);

  struct DriverHandler
  {
    KODI::JOYSTICK::IDriverHandler* handler;
    bool bPromiscuous;
  };

  // State parameters
  std::string m_strProvider;
  int m_requestedPort;
  unsigned int m_buttonCount;
  unsigned int m_hatCount;
  unsigned int m_axisCount;
  unsigned int m_motorCount;
  bool m_supportsPowerOff;
  CDateTime m_lastActive;
  std::queue<std::string> m_controllersToInstall;
  std::vector<std::future<void>> m_installTasks;

  // Input clients
  std::unique_ptr<KODI::JOYSTICK::CKeymapHandling> m_appInput;
  std::unique_ptr<KODI::JOYSTICK::CRumbleGenerator> m_rumbleGenerator;
  std::unique_ptr<KODI::JOYSTICK::IInputHandler> m_joystickMonitor;
  std::unique_ptr<KODI::JOYSTICK::IButtonMap> m_buttonMap;
  std::unique_ptr<KODI::JOYSTICK::CDeadzoneFilter> m_deadzoneFilter;
  std::vector<DriverHandler> m_driverHandlers;

  // Synchronization parameters
  CCriticalSection m_handlerMutex;
  CCriticalSection m_controllerInstallMutex;
};
} // namespace PERIPHERALS