`PS` button raises RuntimeError('There is no current event loop in thread %r.'
See original GitHub issueI’m trying to create a keyboard/mouse setup for anki with my controller.
I start ds4drv --hidraw
:
[info][controller 1] Created devices /dev/input/js0 (joystick) /dev/input/event21 (evdev)
[info][controller 1] Connected to Bluetooth Controller (A4:53:85:86:E2:AB hidraw4)
[info][hidraw] Scanning for devices
[info][controller 1] Battery: 62%
So far nothing happens when I push buttons on the controller (except PS
).
Upon pressing the PS
button however, the following Exceptions show up:
[info][controller 1] Switching to profile: kbmouse
Exception ignored in: <function InputDevice.__del__ at 0x7f80352723a0>
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 159, in __del__
self.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 304, in close
super().close()
File "/usr/local/lib/python3.8/dist-packages/evdev/eventio_async.py", line 54, in close
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
Exception ignored in: <function InputDevice.__del__ at 0x7f80352723a0>
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 159, in __del__
self.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 304, in close
super().close()
File "/usr/local/lib/python3.8/dist-packages/evdev/eventio_async.py", line 54, in close
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 109, in run
self.loop.run()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 101, in run
callback()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 106, in read_report
self.fire_event("device-report", report)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 38, in fire_event
self.loop.fire_event(event, *args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 86, in fire_event
self.process_events()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 92, in process_events
callback(*args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/action.py", line 73, in _handle_report
self.handle_report(report)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/binding.py", line 105, in handle_report
binding.callback(report, *binding.args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/binding.py", line 62, in <lambda>
lambda r: self.controller.next_profile())
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 61, in next_profile
self.load_profile(self.profiles[next_index])
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 47, in load_profile
self.load_options(profile_options)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 93, in load_options
self.fire_event("load-options", options)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 38, in fire_event
self.loop.fire_event(event, *args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 86, in fire_event
self.process_events()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 92, in process_events
callback(*args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/input.py", line 75, in load_options
self.joystick.device.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/uinput.py", line 205, in close
self.device.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 304, in close
super().close()
File "/usr/local/lib/python3.8/dist-packages/evdev/eventio_async.py", line 54, in close
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
After that, no button presses on the controller do anything anymore (not even PS
).
I also noticed, that when I start it with ds4drv --hidraw --mapping keyboard
, I can move the mouse with the right stick, type wasd with the left stick and do some other things.
ds4drv --hidraw --mapping keyboard
[info][controller 1] Connected to Bluetooth Controller (A4:53:85:86:E2:AB hidraw4)
[info][hidraw] Scanning for devices
[info][controller 1] Battery: 62%
When I then press PS
once, I can also use the trackpad to move the mouse, but the following error appears:
[info][controller 1] Switching to profile: kbmouse
Exception ignored in: <function InputDevice.__del__ at 0x7f9d612cc3a0>
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 159, in __del__
self.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 304, in close
super().close()
File "/usr/local/lib/python3.8/dist-packages/evdev/eventio_async.py", line 54, in close
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
If I hit PS
again, the controller ceases that functionality with:
[info][controller 1] Switching to profile: xpad
And upon pressing PS
yet again, the long Error we’ve already seen shows up:
[info][controller 1] Switching to profile: default
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 109, in run
self.loop.run()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 101, in run
callback()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 106, in read_report
self.fire_event("device-report", report)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 38, in fire_event
self.loop.fire_event(event, *args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 86, in fire_event
self.process_events()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 92, in process_events
callback(*args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/action.py", line 73, in _handle_report
self.handle_report(report)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/binding.py", line 105, in handle_report
binding.callback(report, *binding.args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/binding.py", line 62, in <lambda>
lambda r: self.controller.next_profile())
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 61, in next_profile
self.load_profile(self.profiles[next_index])
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 47, in load_profile
self.load_options(profile_options)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 93, in load_options
self.fire_event("load-options", options)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/__main__.py", line 38, in fire_event
self.loop.fire_event(event, *args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 86, in fire_event
self.process_events()
File "/usr/local/lib/python3.8/dist-packages/ds4drv/eventloop.py", line 92, in process_events
callback(*args)
File "/usr/local/lib/python3.8/dist-packages/ds4drv/actions/input.py", line 75, in load_options
self.joystick.device.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/uinput.py", line 205, in close
self.device.close()
File "/usr/local/lib/python3.8/dist-packages/evdev/device.py", line 304, in close
super().close()
File "/usr/local/lib/python3.8/dist-packages/evdev/eventio_async.py", line 54, in close
loop = asyncio.get_event_loop()
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
No button pressing on the controller yields any reaction now.
My ~/.config/ds4drv.conf
(copied from some sample configuration):
# Many of the settings used here are directly connected to their command line
# counterparts, see "ds4drv --help" for more information about available options.
##
# Global options
##
[ds4drv]
# Run ds4drv in background as a daemon
#daemon = true
# Location of the log file in daemon mode
#daemon-log = ~/.cache/ds4drv.log
# Location of the PID file in daemon mode
#daemon-pid = /tmp/ds4drv.pid
# Enable hidraw mode
#hidraw = true
##
# Controller settings
#
# This is the default profile for each controller.
# Multiple controllers slots are defined by increasing the number.
#
# Controller sections contain:
# Key: A option, these are the same options that can used on the command line
# but without the "--" prefix.
# Value: The option's value, should be "true" if no value is needed.
#
# See "ds4drv --help" for a complete list of available options.
##sdwasawdwasdadawdsdadaw
[controller:1]
# Enables LED flash on low battery
#battery-flash = true
# Sets LED color
#led = 0000ff
# Enables profile switching
profile-toggle = PS
# Profiles to cycle through
profiles = kbmouse,xpad
##
# Profiles
#
# Profiles allows switching controller settings during runtime.
#
# Profile sections always require a name and are then enabled on a controller
# with "profiles = <profile1>[,<profile2>]".
#
# The same settings available for controllers are used here.
##
[profile:xpad]
led = ff0000
# Emulate the same button mapping as wired Xbox 360 controllers
emulate-xpad = true
[profile:kbmouse]
led = 00ff00
# Enable trackpad mouse
trackpad-mouse = true
# Custom button mapping
mapping = keyboard
# Custom action bindings
bindings = exec_stuff
##
# Mappings
#
# Mappings let you map buttons and sticks to mouse, key and joystick events.
#
# Mapping sections always require a name and are then enabled in a profile
# with "mapping = <name>".
#
# Mapping sections contain:
# Key: A Linux input event, see /usr/include/linux/input-event-codes.h for a complete list
# Value: Button on the DS4, use --dump-reports to see all the available buttons
##
[mapping:keyboard]
# General button to key mapping
KEY_UP = dpad_up
KEY_LEFT = dpad_left
KEY_DOWN = dpad_down
KEY_RIGHT = dpad_right
KEY_Z = button_cross
KEY_X = button_circle
# Turn analog stick directions into buttons
KEY_W = -left_analog_y
KEY_A = -left_analog_x
KEY_S = +left_analog_y
KEY_D = +left_analog_x
# Map relative mouse movement to a analog stick
REL_X = right_analog_x
REL_Y = right_analog_y
# Map mouse buttons
BTN_LEFT = button_r2
BTN_RIGHT = button_l2
# Emulate mouse wheel on r1 and l1
REL_WHEELUP = button_l1
REL_WHEELDOWN = button_r1
# Mouse settings
#mouse_sensitivity = 0.6
#mouse_deadzone = 5
# Scroll wheel emulation settings (values are in seconds)
#mouse_scroll_repeat_delay = 0.25 # How long to wait before continual scrolling
#mouse_scroll_delay = 0.05 # Lower this to scroll faster; raise to scroll slower
##
# Bindings
#
# Bindings let you bind button combos to special built-in actions.
#
# Binding sections can be defined with a name and are then enabled in a profile
# with "bindings = <name>".
#
# It's also possible to define a global bindings section that is enabled
# on all profiles.
#
# Sections contains:
# Key: A button combo
# Value: An action, see next section for valid actions.
#
#
# Valid actions:
# next-profile Loads the next profile
# prev-profile Loads the previous profile
# load-profile <profile> Loads the specified profile
# exec <command> [arg1] [arg2] ... Executes the command with
# specified arguments
# exec-background <command> [arg1] [arg2] ... Same as exec but launches in
# the background
#
#
# Actions will be pre-processed and replace variables with real values.
#
# Valid variables:
# $profile The current profile
# $name Pretty name of the current device
# $device_addr Bluetooth address of the device
# $report.<attribute> Replace <attribute> with a valid attribute,
# use --dump-reports to see which are available
##
[bindings]
# Cycle profiles
#PS+Right = next-profile
#PS+Left = prev-profile
# Go directly to specified profile
PS+Up = load-profile kbmouse
#PS+Down = load-profile default
[bindings:exec_stuff]
# Execute a command in the foreground, blocking until it has finished
PS+Cross = exec echo '$name'
# Execute a command in the background
PS+Triangle = exec-background sh -c 'echo "disconnect $device_addr" | bluetoothctl'
- Why do these errors show up and how do I fix them?
- The second example gets me to believe that the controller is a privileged paperweight in
default
profile - is that because my configuration is faulty? Is there some way to keep the controller from enteringdefault
profile, cycling only the others? - Is there a way to start ds4drv with a specific profile (e.g.
kbmouse
) without having to switch profile using the controller?
Issue Analytics
- State:
- Created 3 years ago
- Comments:13 (1 by maintainers)
Top GitHub Comments
It seems no one is really interested in this anymore, however, I found a solution with python 2.7 that has the following error:
Just telling you to comment out a line in the source code would not look like a clever idea, so let me explain why it is indeed a viable path.
First of all, due to Python2.7 and Python3+, the error you can see above is related to how the
super()
functions should be used. Just open that file/usr/local/lib/python2.7/dist-packages/evdev/device.py
and look for theclose()
function. You will see it indeed looks like as in the error message, however, for this version of python we need to pass the class’ name as well as an argument, i.e.,super(PARENT_CLASS)
. By looking at the main class definition of thisdevice.py
, we see it is an instance of theEventIO
. Now, let’s check where does it come from! In theimport
section, we can see it can come from two sources:If we take a closer look at these sources (by finding the relevant source codes of either
/usr/local/lib/python2.7/dist-packages/evdev/eventio.py
or/usr/local/lib/python2.7/dist-packages/evdev/eventio_async.py
, we can deduce the following.eventio_async.py
does not have aclose()
function, whileeventio.py
has an emptyclose()
function, i.e.,Therefore, actually calling properly this function makes not too much sense, so we can surely go to line 304 in
/usr/local/lib/python2.7/dist-packages/evdev/device.py
and comment out the function callsuper().close()
or the already tried to changesuper(EventIO).close()
.After doing this,
ds4drv
works as expected, at least in the terminal (did not have time to check with games yet) without crashing:I hope it helps everyone being in a huge need of PS4 controllers and Linux gaming 😃 The solution might be a solution as well for other python versions complaining about the same problem by default.
Since the topic of mapping to SDL has been brought up, time to shill a project of mine. I made a GUI utility for mapping an evdev controller to the SDL GameController spec. The program was made as a replacement for the proprietary SDL2 Gamepad Tool and it offers feature parity. The app is written in Qt using Qt Quick/QML for the GUI. There is an AppImage available that has been tested on Fedora 32 and Ubuntu 20.04; I don’t think it has ever been tested on Fedora 33 so I should do that sometime.
Latest release page: https://gitlab.com/ryochan7/sdl2-gamepad-mapper/-/releases/v0.0.3
SDL2_Gamepad_Mapper-0.0.3-x86_64.AppImage: https://drive.google.com/file/d/12CtYjPbP8YLN7dCIJiKX5EcNdf4PIz4g/view?usp=sharing
Repo: https://gitlab.com/ryochan7/sdl2-gamepad-mapper