7

Is it possible to "rumble" my wireless Xbox 360 controller for PC with Python? I've only found solution for reading input but I cant find information about vibration/rumble.

EDIT:

Following the code provided by @AdamRosenfield I get the following error.

Traceback (most recent call last):
  File "C:\Users\Usuario\Desktop\rumble.py", line 8, in <module>
    xinput = ctypes.windll.Xinput  # Load Xinput.dll
  File "C:\Python27\lib\ctypes\__init__.py", line 435, in __getattr__
    dll = self._dlltype(name)
  File "C:\Python27\lib\ctypes\__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
WindowsError: [Error 126] The specified module could not be found. 

Plese note that the last error was translated from Spanish.

Belohlavek
  • 167
  • 3
  • 13

1 Answers1

8

It's possible, but it's not easy. In C, you'd use the XInputSetState() function to control the rumble. To access that from Python, you'd have to either compile a Python extension written in C or use the ctypes library.

Something like this should work, though bear in mind I haven't tested this:

import ctypes

# Define necessary structures
class XINPUT_VIBRATION(ctypes.Structure):
    _fields_ = [("wLeftMotorSpeed", ctypes.c_ushort),
                ("wRightMotorSpeed", ctypes.c_ushort)]

xinput = ctypes.windll.xinput1_1  # Load Xinput.dll

# Set up function argument types and return type
XInputSetState = xinput.XInputSetState
XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)]
XInputSetState.restype = ctypes.c_uint

# Now we're ready to call it.  Set left motor to 100%, right motor to 50%
# for controller 0
vibration = XINPUT_VIBRATION(65535, 32768)
XInputSetState(0, ctypes.byref(vibration))

# You can also create a helper function like this:
def set_vibration(controller, left_motor, right_motor):
    vibration = XINPUT_VIBRATION(int(left_motor * 65535), int(right_motor * 65535))
    XInputSetState(controller, ctypes.byref(vibration))

# ... and use it like so
set_vibration(0, 1.0, 0.5)
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • Thanks for answering, I'm getting error with "ctypes.struct": It is not a valid attribute. Also I don't know where "ctypes.struct" comes from! – Belohlavek Nov 03 '13 at 03:43
  • @Belohlavek: Whoops, should be `Structure`, not `struct`. – Adam Rosenfield Nov 03 '13 at 04:13
  • Good weekend project! +1 – Burhan Khalid Nov 03 '13 at 04:26
  • @AdamRosenfield I'm getting this error WindowsError: [Error 126] The specified module could not be found. I've read that it could be a character conflict but still do not see anything wrong! – Belohlavek Nov 03 '13 at 04:33
  • @BurhanKhalid Thanks! I'm trying to rumble/vibrate (in a very subtle way) my controller following the beat of the music that I listen while playing games. – Belohlavek Nov 03 '13 at 04:37
  • 2
    @Belohlavek: Do you have the DirectX SDK installed? The XInput library is only installed by default on Windows Vista and Windows 8, according to the docs. If you do have the DirectX SDK installed and it's still not finding the DLL, then you need to manually load the library with something like `xinput = ctypes.windll.LoadLibrary(r'C:\path\to\Xinput.dll')` instead. – Adam Rosenfield Nov 04 '13 at 00:52
  • The installation for the SDK partially failed. It installed some software with samples and code, yet it shows an error message telling me that installation failed and I should try closing all programs and running it again. Didn't work. I've also tried to load the library but there was no DLL on the DX SDK's folder, I tried using the one on System32 but it doesn't work either (same ERROR 126 message). The rumble samples (binaries) work just fine with my controller. Also, i have 3 versions of Xinput_(number).dll! – Belohlavek Nov 04 '13 at 03:25
  • 2
    @Belohlavek: Apparently the actual DLL name contains a version number in it. Try using `ctypes.windll.xinput1_1` instead (or `xinput1_3` or `XInput9_1_0`, or really whatever the name of your `C:\Windows\System32\xinput.dll` is). – Adam Rosenfield Nov 04 '13 at 16:21
  • It worked with "xinput = ctypes.windll.XInput9_1_0", very subtle vibration, I guess I will have to create a loop in order to get more rumble. Thanks! EDIT: Mmhh... `while True: set_vibration(0, 60000, 60000)` does not give me a constant rumble! – Belohlavek Nov 04 '13 at 20:32
  • I'm trying to do the same, but in Ubuntu 14.04. Any lead? – Sidmeister Sep 24 '15 at 19:46