Skip to content

Commit aa5713b

Browse files
author
Fayvel Victor
committed
Add special SDL2 joystick event system for input config
The SDL1.2 system cannot cope with Dualshock and similar controllers. After pressing the config button, an random axis will be configured. This happens because the state of the device (with 27 or more axis) changes all the time. This problem can be avoided for these devices under Linux when SDL2 is used together with its event system. These random movements doesn't anymore with these joysticks and the hid_sony driver in SDL2+SDL_PollEvent. This seem to be fixable with SDL1.2 because it just cannot handle newer devices. Also the SDL_PollEvent doesn't work with the ctypes version of PySDL for unknown reasons. Thus the implementation cannot be shared between SDL1.2 and SDL2. To use the new input detection, m64py must be started with the sdl2 option and a version of mupen64plus compiled against SDL2. $ m64py --sdl2
1 parent 783f5c6 commit aa5713b

File tree

1 file changed

+85
-2
lines changed

1 file changed

+85
-2
lines changed

src/m64py/frontend/joystick.py

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121

2222
from m64py.opts import SDL2
2323
from m64py.frontend.log import log
24+
import ctypes
2425

2526
if SDL2:
2627
from m64py.SDL2 import SDL_WasInit, SDL_InitSubSystem, SDL_INIT_JOYSTICK
2728
from m64py.SDL2 import SDL_JoystickOpen, SDL_JoystickClose, SDL_NumJoysticks, SDL_JoystickNameForIndex
2829
from m64py.SDL2 import SDL_JoystickNumAxes, SDL_JoystickNumButtons, SDL_JoystickNumHats, SDL_JoystickNumBalls
29-
from m64py.SDL2 import SDL_JoystickGetAxis, SDL_JoystickGetButton, SDL_JoystickGetHat, SDL_JoystickUpdate
30+
from m64py.SDL2 import SDL_JoystickGetAxis, SDL_JoystickGetButton, SDL_JoystickGetHat, SDL_JoystickUpdate, SDL_JoystickInstanceID
31+
from m64py.SDL2 import SDL_Event, SDL_PollEvent
32+
from m64py.SDL2 import SDL_JOYAXISMOTION, SDL_JOYHATMOTION, SDL_JOYBALLMOTION, SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP
3033
else:
3134
from m64py.SDL import SDL_WasInit, SDL_InitSubSystem, SDL_INIT_JOYSTICK
3235
from m64py.SDL import SDL_JoystickOpen, SDL_JoystickClose, SDL_NumJoysticks, SDL_JoystickName
@@ -81,10 +84,20 @@ def init(self):
8184
self.joystick_names.append(SDL_JoystickNameForIndex(i))
8285
else:
8386
self.joystick_names.append(SDL_JoystickName(i))
84-
self.joystick_timer.timeout.connect(self.process_events)
87+
88+
if SDL2:
89+
self.joystick_timer.timeout.connect(self.process_events_sdl2)
90+
else:
91+
self.joystick_timer.timeout.connect(self.process_events)
8592
else:
8693
log.info("couldn't initialize SDL joystick support")
8794

95+
def clear_events(self):
96+
if SDL2:
97+
event = SDL_Event()
98+
while SDL_PollEvent(ctypes.byref(event)) != 0:
99+
pass
100+
88101
def open(self, stick=0):
89102
if self.joystick:
90103
self.close()
@@ -114,6 +127,7 @@ def open(self, stick=0):
114127
self.hats[i] = SDL_JoystickGetHat(self.joystick, i)
115128
self.hat_repeat_timers[i] = QTime()
116129

130+
self.clear_events()
117131
self.joystick_timer.start(self.event_timeout)
118132
return True
119133
else:
@@ -181,3 +195,72 @@ def process_events(self):
181195
dx, dy = self.joystick.get_ball(i)
182196
if dx != 0 or dy != 0:
183197
self.trackball_value_changed.emit(i, dx, dy)
198+
199+
def process_events_sdl2(self):
200+
if not self.joystick:
201+
return
202+
203+
stickid = SDL_JoystickInstanceID(self.joystick)
204+
event = SDL_Event()
205+
while SDL_PollEvent(ctypes.byref(event)) != 0:
206+
if event.type == SDL_JOYAXISMOTION:
207+
if stickid != event.jaxis.which:
208+
continue
209+
moved = event.jaxis.value
210+
i = event.jaxis.axis
211+
if abs(moved) >= self.deadzones[i]:
212+
if moved != self.axes[i]:
213+
delta_moved = abs(self.axes[i] - moved)
214+
if delta_moved >= self.sensitivities[i]:
215+
self.axis_value_changed.emit(i, moved)
216+
self.axes[i] = moved
217+
self.axis_repeat_timers[i].restart()
218+
elif self.auto_repeat and moved != 0:
219+
if self.axis_repeat_timers[i].elapsed() >= self.auto_repeat_delay:
220+
self.axis_value_changed.emit(i, moved)
221+
self.axes[i] = moved
222+
else:
223+
self.axis_repeat_timers[i].restart()
224+
else:
225+
self.axis_value_changed.emit(i, 0)
226+
227+
elif event.type == SDL_JOYHATMOTION:
228+
if stickid != event.jhat.which:
229+
continue
230+
changed = event.jhat.value
231+
i = event.jhat.hat
232+
if changed != self.hats[i]:
233+
self.hat_value_changed.emit(i, changed)
234+
self.hats[i] = changed
235+
self.hat_repeat_timers[i].restart()
236+
elif self.auto_repeat and changed != 0:
237+
if self.hat_repeat_timers[i].elapsed() >= self.auto_repeat_delay:
238+
self.hat_value_changed.emit(i, changed)
239+
self.hats[i] = changed
240+
else:
241+
self.hat_repeat_timers[i].restart()
242+
243+
elif event.type == SDL_JOYBALLMOTION:
244+
if stickid != event.jball.which:
245+
continue
246+
dx = event.jball.xrel
247+
dy = event.jball.yrel
248+
i = event.jball.ball
249+
if dx != 0 or dy != 0:
250+
self.trackball_value_changed.emit(i, dx, dy)
251+
252+
elif event.type == SDL_JOYBUTTONDOWN or event.type == SDL_JOYBUTTONUP:
253+
if stickid != event.jbutton.which:
254+
continue
255+
changed = event.jbutton.state
256+
i = event.jbutton.button
257+
if changed != self.buttons[i]:
258+
self.button_value_changed.emit(i, changed)
259+
self.buttons[i] = changed
260+
self.button_repeat_timers[i].restart()
261+
elif self.auto_repeat and changed != 0:
262+
if self.button_repeat_timers[i].elapsed() >= self.auto_repeat_delay:
263+
self.button_value_changed.emit(i, changed)
264+
self.button[si] = changed
265+
else:
266+
self.button_repeat_timers[i].restart()

0 commit comments

Comments
 (0)