-
Notifications
You must be signed in to change notification settings - Fork 0
/
joysticks.py
145 lines (119 loc) · 4.39 KB
/
joysticks.py
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
from PySide2.QtCore import QObject, Signal, Slot
import time
import platform
if platform.system() == 'Windows':
import joystickapi_win as joystickapi
else:
import joystickapi_linux as joystickapi
SNES_BUTTON_A = 0x01
SNES_BUTTON_B = 0x02
SNES_BUTTON_X = 0x04
SNES_BUTTON_Y = 0x08
SNES_BUTTON_L = 0x10
SNES_BUTTON_R = 0x20
SNES_BUTTON_SELECT = 0x40
SNES_BUTTON_START = 0x80
SNESS_BUTTONS_COUNT = 8
SNESS_LONG_BUTTON_PRESS_TIME_SEC = 2
ENUMERATE_JOYSTICKS_DELAY_SEC = 3
class Joystick(QObject):
def __init__(self):
QObject.__init__(self)
self._x = 0
self._y = 0
self._buttons = 0
self._long_press_buttons = 0
self._button_long_press_time = {}
def x(self):
return self._x
def y(self):
return self._y
def buttons(self):
return self._buttons
def long_press_buttons(self):
return self._long_press_buttons
polled = Signal(int, int, int)
changed = Signal(int, int, int)
x_pressed = Signal(int)
y_pressed = Signal(int)
buttons_pressed = Signal(int)
long_press_buttons_pressed = Signal(int)
unplugged = Signal()
def update(self, x, y, buttons):
new_x = x if (x != self._x) else 0
new_y = y if (y != self._y) else 0
new_buttons = buttons & ~self._buttons
long_press_buttons = 0
current_time = time.time()
for b in [1 << i for i in range(1, SNESS_BUTTONS_COUNT+1)]:
if buttons & b:
b_long_press_time = self._button_long_press_time.get(b)
if b_long_press_time is None:
self._button_long_press_time[b] = current_time + SNESS_LONG_BUTTON_PRESS_TIME_SEC
elif b_long_press_time <= current_time:
long_press_buttons = long_press_buttons | b
else:
self._button_long_press_time.pop(b, None)
new_long_press_buttons = long_press_buttons & ~self._long_press_buttons
has_changed = (x != self._x) or \
(y != self._y) or \
(buttons != self._buttons) or \
(long_press_buttons != self._long_press_buttons)
self._x = x
self._y = y
self._buttons = buttons
self._long_press_buttons = long_press_buttons
self.polled.emit(x, y, buttons)
if has_changed:
self.changed.emit(x, y, buttons)
if new_x:
self.x_pressed.emit(new_x)
if new_y:
self.y_pressed.emit(new_y)
if new_buttons:
self.buttons_pressed.emit(new_buttons)
if new_long_press_buttons:
self.long_press_buttons_pressed.emit(new_long_press_buttons)
def unplug(self):
self.unplugged.emit()
class Joysticks(QObject):
def __init__(self):
QObject.__init__(self)
self._devices = None
self._devices_cache = None
self._joysticks = {}
self._last_refresh = time.time()
self._next_enumerate = time.time()
self._refreshes = 0
self.refresh()
@Slot(result=float)
def refreshesPerSecond(self):
new_time = time.time()
result = self._refreshes / (new_time - self._last_refresh)
self._last_refresh = new_time
self._refreshes = 0
return result
refreshed = Signal()
added = Signal(Joystick)
@Slot()
def refresh(self):
#if self._devices is None: # or self._next_enumerate <= time.time():
# self._next_enumerate = time.time() + ENUMERATE_JOYSTICKS_DELAY_SEC
self._devices, self._devices_cache = joystickapi.enumerate_joysticks(self._devices, self._devices_cache)
new_indices = set()
self._devices, connected_joysticks = joystickapi.poll_joysticks(self._devices)
for index, values in connected_joysticks.items():
if index not in self._joysticks:
self._joysticks[index] = Joystick()
new_indices.add(index)
x, y, buttons = values
self._joysticks[index].update(x, y, buttons)
missing_indices = self._joysticks.keys() - connected_joysticks.keys()
for i in missing_indices:
self._joysticks.pop(i).unplug()
for i in new_indices:
self.added.emit(self._joysticks[i])
self._refreshes = self._refreshes + 1
self.refreshed.emit()
def joysticks(self):
return self._joysticks.values()