vgamepad

repository·main·Indexed 42 days ago

https://github.com/yannbouteiller/vgamepad

A Python library for emulating XBox360 and DualShock4 gamepads to provide analog and digital inputs to games or applications. On Windows, it serves as an interface for the ViGEmBus C++ framework and supports rumble and LED notifications. It also provides experimental support for Linux via libevdev and uinput.

Tokens
2.8K
Snippets
10
Records
12
Agent score
54%

What's inside vgamepad

  1. Overview of vgamepad

    main

    vgamepad is a Python library used to emulate XBox360 and DualShock4 gamepads on your system. It allows Python scripts to provide analog and digital inputs to video games or other applications that require gamepad controllers.

    On Windows, the library acts as a Python interface for the ViGEmBus C++ framework.

  2. Understand Linux implementation limitations

    main

    On Linux, vgamepad relies on libevdev and manages a virtual uinput device. This implementation is experimental and differs significantly from the Windows version (which uses ViGEmBus).

    Key Differences and Limitations

    • Emulation Model: It emulates a subset of X360 and DS4 capabilities via evdev. It is not a 1:1 emulation of physical hardware.
    • Input Mapping: Detected buttons, ordering, and axes directions may differ from Windows depending on the application using the input.
    • Missing Features:
      • Force feedback / LEDs
      • DS4 touchpad / motion sensor (no extended reports)
      • DS4 trigger button events (only axis events are sent)
      • X360 "guide" (mode) button

    Note: Because Linux support is experimental, it is highly recommended to pin the exact version of vgamepad in your project dependencies to avoid breaking changes.

  3. How virtual gamepad reports work

    main

    In vgamepad, the state of a virtual gamepad (such as pressed buttons or joystick values) is referred to as a report.

    To change the state of the gamepad, you use user-friendly API functions (like press_button or left_joystick). However, these changes are only local to the object until you call the update() method. You must call update() to send the modified report to the computer so the system recognizes the input.

    import vgamepad as vg
    
    gamepad = vg.VX360Gamepad()
    gamepad.press_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_A)
    gamepad.update()  # This sends the state to the system
  4. Install vgamepad on Linux

    main

    To use vgamepad on Linux, you must first ensure your user has permission to access /dev/uinput. Follow these steps to set up permissions and install the package.

    1. Configure uinput permissions

    Temporary (Current session only): Run the following command to grant access for the current session:

    sudo chmod +0666 /dev/uinput

    Permanent (Recommended): To ensure permissions persist after a reboot, create a udev rule:

    1. Create/edit the rule file:
      sudo nano /etc/udev/rules.d/50-uinput.rules
    2. Paste the following line into the file:
       ```text
    KERNEL=="uinput", TAG+="uaccess"
    1. Save and exit (CTRL+o, ENTER, CTRL+x).

    2. Install the package

    Install vgamepad using pip into your active Python environment:

    pip install vgamepad
  5. Install vgamepad on Windows

    main

    To install vgamepad on Windows, run the following command in your terminal (e.g., Anaconda Prompt):

    pip install vgamepad

    Note: This command automatically triggers the installer for the ViGEmBus driver. You must accept the license agreement, allow the installer to modify your PC, and wait for completion. Only ViGEmBus 1.17.333.0 has been explicitly tested.

    If you need to skip the automatic installation of the ViGEmBus driver, set the environment variable VGAMEPAD_SKIP_VIGEMBUS_INSTALL to true before running the pip command.

  6. Use the VDS4Gamepad class

    main

    The VDS4Gamepad class emulates a DualShock 4 controller.

    Button Control

    • Digital Buttons: Use press_button and release_button with constants from vg.DS4_BUTTONS.
    • Special Buttons: Use press_special_button and release_special_button with constants from vg.DS4_SPECIAL_BUTTONS (e.g., DS4_SPECIAL_BUTTON_PS).
    • Directional Pad (D-Pad): Use directional_pad(direction=...) with constants from vg.DS4_DPAD_DIRECTIONS.

    Joystick and Trigger Control

    • Integers: Triggers (0 to 255), Joysticks (0 to 255).
    • Floats: Triggers (0.0 to 1.0), Joysticks (-1.0 to 1.0).

    Note: Since version 0.1.0, the DS4 Y axis on joysticks is inverted compared to the X360 API to match native ViGEm behavior.

    Reset

    Call reset() to return the gamepad to its default state.

    import vgamepad as vg
    
    gamepad = vg.VDS4Gamepad()
    
    # Digital Button
    gamepad.press_button(button=vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE)
    
    # Special Button
    gamepad.press_special_button(special_button=vg.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_PS)
    
    # D-Pad
    gamepad.directional_pad(direction=vg.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NORTH)
    
    # Triggers/Joysticks (Float)
    gamepad.left_trigger_float(value_float=0.5)
    
    gamepad.update()
  7. Use the VX360Gamepad class

    main

    The VX360Gamepad class emulates an Xbox 360 controller. Creating an instance connects the virtual gamepad to your system via the ViGEmBus driver; it remains connected until the object is destroyed.

    Button Control

    Use press_button(button=...) and release_button(button=...) with constants from vg.XUSB_BUTTON.

    Joystick and Trigger Control

    You can use raw integer values or float values:

    • Integers: Triggers (0 to 255), Joysticks (-32768 to 32767).
    • Floats: Triggers (0.0 to 1.0), Joysticks (-1.0 to 1.0).

    Reset

    Call reset() to return the gamepad to its default state.

    import vgamepad as vg
    
    gamepad = vg.VX360Gamepad()
    
    # Buttons
    gamepad.press_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_A)
    gamepad.update()
    
    # Triggers (Integer)
    gamepad.left_trigger(value=100)
    
    # Joysticks (Float)
    gamepad.left_joystick_float(x_value_float=-0.5, y_value_float=0.0)
    
    gamepad.update()
  8. Handle Rumble and LED notifications (Windows only)

    main

    On Windows, you can register a callback function to react when a game or application sends rumble (vibration) or LED ring updates to the virtual gamepad. This is useful for synchronizing your own logic with the gamepad's state changes.

    Callback Signature

    Your callback must accept exactly 6 parameters: my_callback(client, target, large_motor, small_motor, led_number, user_data)

    • client: ViGEm bus ID
    • target: ViGEm device ID
    • large_motor: Integer [0, 255]
    • small_motor: Integer [0, 255]
    • led_number: Integer [0, 255]
    • user_data: Placeholder (do not use)

    Registration

    Use register_notification(callback_function=...) to start listening, and unregister_notification() to stop.

    def my_callback(client, target, large_motor, small_motor, led_number, user_data):
        print(f"Large motor: {large_motor}, Small motor: {small_motor}, LED: {led_number}")
    
    gamepad.register_notification(callback_function=my_callback)
    
    # ... later ...
    
    gamepad.unregister_notification()
  9. Reference: DS4_DPAD_DIRECTIONS constants

    main

    Available directional pad (HAT) values for VDS4Gamepad using the vg.DS4_DPAD_DIRECTIONS enum.

    class DS4_DPAD_DIRECTIONS(IntEnum):
        DS4_BUTTON_DPAD_NONE = 0x8
        DS4_BUTTON_DPAD_NORTHWEST = 0x7
        DS4_BUTTON_DPAD_WEST = 0x6
        DS4_BUTTON_DPAD_SOUTHWEST = 0x5
        DS4_BUTTON_DPAD_SOUTH = 0x4
        DS4_BUTTON_DPAD_SOUTHEAST = 0x3
        DS4_BUTTON_DPAD_EAST = 0x2
        DS4_BUTTON_DPAD_NORTHEAST = 0x1
        DS4_BUTTON_DPAD_NORTH = 0x0
  10. Reference: DS4_SPECIAL_BUTTONS constants

    main

    Available special button constants for VDS4Gamepad using the vg.DS4_SPECIAL_BUTTONS enum.

    class DS4_SPECIAL_BUTTONS(IntFlag):
        DS4_SPECIAL_BUTTON_PS = 1 << 0
        DS4_SPECIAL_BUTTON_TOUCHPAD = 1 << 1  # Windows only, no effect on Linux
  11. Reference: DS4_BUTTONS constants

    main

    Available digital button constants for VDS4Gamepad using the vg.DS4_BUTTONS enum.

    class DS4_BUTTONS(IntFlag):
        DS4_BUTTON_THUMB_RIGHT = 1 << 15
        DS4_BUTTON_THUMB_LEFT = 1 << 14
        DS4_BUTTON_OPTIONS = 1 << 13
        DS4_BUTTON_SHARE = 1 << 12
        DS4_BUTTON_TRIGGER_RIGHT = 1 << 11
        DS4_BUTTON_TRIGGER_LEFT = 1 << 10
        DS4_BUTTON_SHOULDER_RIGHT = 1 << 9
        DS4_BUTTON_SHOULDER_LEFT = 1 << 8
        DS4_BUTTON_TRIANGLE = 1 << 7
        DS4_BUTTON_CIRCLE = 1 << 6
        DS4_BUTTON_CROSS = 1 << 5
        DS4_BUTTON_SQUARE = 1 << 4
  12. Reference: XUSB_BUTTON constants

    main

    Available button constants for VX360Gamepad using the vg.XUSB_BUTTON enum.

    class XUSB_BUTTON(IntFlag):
        XUSB_GAMEPAD_DPAD_UP = 0x0001
        XUSB_GAMEPAD_DPAD_DOWN = 0x0002
        XUSB_GAMEPAD_DPAD_LEFT = 0x0004
        XUSB_GAMEPAD_DPAD_RIGHT = 0x0008
        XUSB_GAMEPAD_START = 0x0010
        XUSB_GAMEPAD_BACK = 0x0020
        XUSB_GAMEPAD_LEFT_THUMB = 0x0040
        XUSB_GAMEPAD_RIGHT_THUMB = 0x0080
        XUSB_GAMEPAD_LEFT_SHOULDER = 0x0100
        XUSB_GAMEPAD_RIGHT_SHOULDER = 0x0200
        XUSB_GAMEPAD_GUIDE = 0x0400
        XUSB_GAMEPAD_A = 0x1000
        XUSB_GAMEPAD_B = 0x2000
        XUSB_GAMEPAD_X = 0x4000
        XUSB_GAMEPAD_Y = 0x8000