Closed toonn closed 6 years ago
Oh and how about sixaxis support? This'd just be a bonus though.
Your extension sounds great.
Rumble support on the Xbox controller should be possible since I have used that before.
Sixaxis should work over USB, Bluetooth support is on my TODO list.
Your approach is probably fine. Ignore events that you do not care about. I throw everything that evdev gives into InputEvent objects (and emulate that behaviour on Windows+Mac), sync and dropped etc are a bit over-specific for users to care about.
So Rumble already works on Windows. import inputs gamepad = inputs.devices.gamepads[0] gamepad.set_vibration(1,1)
to stop it gamepad.set_vibration(0,0)
Oh, cool. Most kids'll be running windows anyway. Just makes it harder for me to test 🤷♂️. Is the speed variable between 0 and 1, or multiples of 1?
Seems like it's between 0 and 1. Could you throw a NotImplementedException instead of/in addition to printing that the feature is not supported? Rn it's hard to programmatically verify whether the function works or not so I have to duplicate the platform check.
Ok will do. I just managed to make rumble work on Linux so will tidy up that and add it to inputs soon.
Hi @toonn
So on Linux, it seems a duration must be provided, so the method is now:
gamepad.set_vibration(left_motor, right_motor, duration)
That method on Windows sleeps for duration between start and stop.
If you want the old behaviour on Windows use:
gamepad._start_vibration_win(left_motor, right_motor)
And it will run forever, or until you call:
gamepad._stop_vibration_win()
So the code is now in github version, it will be in a new release on pypi in a week or two.
Oh, well that could've saved me some work. I just implemented all the timing necessary around the set(x,y)/set(0,0) calls : )
Is the method synchronous? Can it be cancelled? What happens if I call it before the last call has finished? Can I read data while rumbling?
Btw, by sixaxis I didn't mean the controller but the rotation/acceleration sensing, is that supported? I couldn't find it in the data but maybe I didn't look hard enough.
Thank you for the work btw, it's very much appreciated.
Ok the whole topic of asyncio and inputs is something I am thinking about for a future task. For now I have made the delay and stop be in a subprocess.
So now using gamepad.set_vibration(left_motor, right_motor, duration) should not block you reading data when rumbling.
If you call gamepad.set_vibration and want to stop it earlier than duration, then you can call gamepad._stop_vibration_win() on Windows.
Actually for cross-platform, you can call gamepad.set_vibration(0, 0, 0) which should reset everything. Might be better I don't know.
Hmm, so if (0, 0, 0) works, would (x, y, z) also work, where those are different from the previous call?
Did you miss the sixaxis part of my question?
Well the Xbox 360 controller has no motion detection. The playstation ones do, they probably report those events on Linux. I have it in my todo list to study those controllers (also see #29 ).
If you use gamepad.set_vibration(left_motor, right_motor, duration), then a new call will override the previous call, however, on Windows, it is theoretically possible to get a race condition if you do: start A - duration 3 secs start B - duration 5 secs end A - happens killing the last 2 seconds of B
So you can either manage the delays yourself by using the _start and _stop methods, or let the user figure it out. I think with scratch the user can replay and see (I am a scratch fan too). However, if it proves a problem, I can look into killing A's reset when B happens.
Hey @zeth: So I've been looking at integrating a Logitech Wireless Gamepad F710 for a Raspberry Pi project I'm working on. I didn't want to implement the interface to the gamepad if I could avoid it, and was pleasantly surprised to find this project. I was able to test the gamepad and have very precise data coming in as I test all of the buttons and such. GREAT WORK!
Though I don't need it, I also attempted to test rumble support -- it didn't work. Here is my traceback:
>>> pads[0].set_vibration(1, 1, 1000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pi/.virtualenvs/myproj/lib/python3.5/site-packages/inputs.py", line 2983, in set_vibration
self._set_vibration_nix(left_motor, right_motor, duration)
File "/home/pi/.virtualenvs/myproj/lib/python3.5/site-packages/inputs.py", line 2969, in _set_vibration_nix
code = self.__get_vibration_code(left_motor, right_motor, duration)
File "/home/pi/.virtualenvs/myproj/lib/python3.5/site-packages/inputs.py", line 2963, in __get_vibration_code
buf_conts = ioctl(self._write_device, 1076905344, inner_event)
OSError: [Errno 14] Bad address
As I have studied the voodoo
that is going on there, it appears that you had implemented the ff_rumble_effect
, however, when calculating the _IOW Linux macro, you came up with 1076905344. When I did a similar exercise (based upon Linux C code here: https://github.com/torvalds/linux/blob/master/include/uapi/linux/input.h), I came up with 1076643200. Simply changing the constant to my calculated value allowed the rumble feature to work for me quite nicely.
HOWEVER, the magic number in the code doesn't really contribute to solid software maintainability. Additionally, as I studied what is occurring in this code, it appears that a new rumble object is defined and sent to the gamepad every time you call set_vibration
. On my device, it starts to fail with a memory error after about 4-5 repeated calls.
>>> pads[0].set_vibration(1, 1, 500)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/pi/myproj/inputs.py", line 3223, in set_vibration
self._set_vibration_nix(left_motor, right_motor, duration)
File "/home/pi/myproj/inputs.py", line 3191, in _set_vibration_nix
code = self.__get_vibration_code(left_motor, right_motor, duration)
File "/home/pi/myproj/inputs.py", line 3185, in __get_vibration_code
buf_conts = ioctl(self._write_device, 1076643200, inner_event)
OSError: [Errno 28] No space left on device
Now, I definitely understand that voodoo
and am willing to help, however, don't want to stick my nose where it doesn't belong. I can certainly cobble together a PR, but from what I can tell (studying this code: https://github.com/flosse/linuxconsole/blob/master/utils/fftest.c), it appears that there are varying rumble mechanisms supported by various gamepads. Coming up with a universal rumble pattern may be tricky and so a more dynamic definition based upon connected devices might make more sense. This is probably why the rumble PR you submitted worked for you but not for me (though from what I can read on the struct definition, I still think you would have calculated the same magic number as I did, so I am not sure why mine is different).
Anyway - how would you like to proceed? How can I help?
Does inputs support the rumble functionality in most gamepads? I realize that's output rather than input but it still seems appropriate.
Thank you for the library! I'm using it to write a scratch 2.0 extension so our CoderDojo can have kids use the full functionality of the gamepads; currently we're limited to mapping buttons to keyboard keys and one of the sticks to the mouse with third party software. All I'm missing is rumble functionality.
One question though, is there a list of what all the
ev_type
s andcode
s mean? For example, I currently completely ignoreSYN_DROPPED
and others, only use events with typesKey
andAbsolute
actually. I'm not sure how robust this 🙈 approach is.