def __init__(self, joystick_index): self.game_controller = None self.joystick = None self.joystick_id = None if sdl2.SDL_IsGameController(joystick_index): self.game_controller = sdl2.SDL_GameControllerOpen(joystick_index) self.joystick = sdl2.SDL_GameControllerGetJoystick( self.game_controller) self.joystick_id = sdl2.SDL_JoystickInstanceID(self.joystick) self.name = sdl2.SDL_GameControllerName(self.game_controller) else: self.joystick = sdl2.SDL_JoystickOpen(joystick_index) self.joystick_id = sdl2.SDL_JoystickInstanceID(self.joystick) self.name = sdl2.SDL_JoystickName(self.joystick)
def __init__(self, device): """Initializes the device data based on the given device. :param device pyGame joystick object """ self._hardware_id = get_device_guid(device) self._windows_id = sdl2.SDL_JoystickInstanceID(device) self._vendor_id = sdl2.SDL_JoystickGetVendor(device) self._product_id = sdl2.SDL_JoystickGetProduct(device) name_object = sdl2.SDL_JoystickName(device) if name_object is None: self._name = "Unknown device" logging.getLogger("system").error( "Encountered an invalid device name for device {:d}".format( self._windows_id)) else: self._name = name_object.decode("utf-8") self._is_virtual = self._name == "vJoy Device" # Default mapping from axis id to physical axis number. This defaults # to a linear 1:1 mapping but for vJoy devices can change self._axes = [] for i in range(sdl2.SDL_JoystickNumAxes(device)): self._axes.append((i + 1, i + 1)) self._buttons = sdl2.SDL_JoystickNumButtons(device) self._hats = sdl2.SDL_JoystickNumHats(device) self._vjoy_id = 0 self._device_id = common.DeviceIdentifier(self._hardware_id, self._windows_id)
def __init__(self, scope, device=0, warnings_enabled=False): """ Parameters: scope: microscope client, instance of scope_client.ScopeClient. device: the numerical index or string name of the input device (from output of enumerate_devices()). warnings_enabled: if True, print debug information to stderr. """ init_sdl() self.device, self.device_name, index, self.is_game_controller = open_device(device) if self.is_game_controller: self.jdevice = sdl2.SDL_GameControllerGetJoystick(self.device) else: self.jdevice = self.device self.device_id = sdl2.SDL_JoystickInstanceID(self.jdevice) self.num_axes = sdl2.SDL_JoystickNumAxes(self.jdevice) self.num_buttons = sdl2.SDL_JoystickNumButtons(self.jdevice) self.num_hats = sdl2.SDL_JoystickNumHats(self.jdevice) self.warnings_enabled = warnings_enabled self.scope = scope._clone() self.event_loop_is_running = False self.quit_event_posted = False self.throttle_delay_command_time_ratio = 1 - self.MAX_AXIS_COMMAND_WALLCLOCK_TIME_PORTION self.throttle_delay_command_time_ratio /= self.MAX_AXIS_COMMAND_WALLCLOCK_TIME_PORTION self._axes_throttle_delay_lock = threading.Lock() self._c_on_axes_throttle_delay_expired_timer_callback = SDL_TIMER_CALLBACK_TYPE(self._on_axes_throttle_delay_expired_timer_callback) self.handle_button_callback = None
def _init_joysticks(self): """Initializes joystick devices.""" for i in range(sdl2.joystick.SDL_NumJoysticks()): joy = sdl2.SDL_JoystickOpen(i) if joy is not None: dev_id = util.device_identifier_from_sdl(joy) self._winid_to_devid[sdl2.SDL_JoystickInstanceID(joy)] = dev_id self._load_calibrations(joy)
def device_identifier_from_sdl(device): """Returns a DeviceIdentifier instance for the given SDL device. :param device SDL joystick device :return DeviceIdentifier instance """ return common.DeviceIdentifier( joystick_handling.get_device_guid(device), sdl2.SDL_JoystickInstanceID(device) )
def poll_sdl_events(self): self.pending = True while self.pending: if self.parent.gamepad_input == sdl.SDL_JoystickInstanceID( self.desired_gamepad): if self.parent.gamepad_pressed != None and self.parent.gamepad_type != None: self.gamepad_pressed = self.parent.gamepad_pressed self.gamepad_type = self.parent.gamepad_type self.pending = False self.destroy()
def __init__(self, sdl_controller_id): self.sdl_controller_id = sdl_controller_id self.sdl_controller = sdl2.SDL_GameControllerOpen(sdl_controller_id) self.sdl_joy = sdl2.SDL_GameControllerGetJoystick(self.sdl_controller) self.sdl_joy_id = sdl2.SDL_JoystickInstanceID(self.sdl_joy) guid = sdl2.SDL_JoystickGetDeviceGUID(self.sdl_joy_id) logging.log(logging.INFO, "Joystick GUID: %s " % guid) logging.log( logging.INFO, "Mapping: %s" % sdl2.SDL_GameControllerMappingForGUID(guid))
def _init_joysticks(self): """Initializes joystick devices.""" for i in range(sdl2.joystick.SDL_NumJoysticks()): joy = sdl2.SDL_JoystickOpen(i) if joy is None: logging.getLogger("system").error( "Invalid joystick device at id {}".format(i)) else: guid = self._get_device_guid(joy) self._joysticks[guid] = joy self._joystick_guid_map[sdl2.SDL_JoystickInstanceID( joy)] = guid self._load_calibrations(guid)
def open(self, device_index): self._sdl_controller = sdl2.SDL_GameControllerOpen(device_index) self._sdl_joystick = sdl2.SDL_GameControllerGetJoystick(self._sdl_controller) self._sdl_joystick_id = sdl2.SDL_JoystickInstanceID(self._sdl_joystick) self._controller_name = sdl2.SDL_JoystickName(self._sdl_joystick) self._num_axis = sdl2.SDL_JoystickNumAxes(self._sdl_joystick), self._num_buttons = sdl2.SDL_JoystickNumButtons(self._sdl_joystick) self._num_balls = sdl2.SDL_JoystickNumBalls(self._sdl_joystick) for btn_index in range(0, self.MAX_BUTTONS): self._button_down[btn_index] = 0 self._button_pressed[btn_index] = 0 self._button_released[btn_index] = 0 if self._sdl_joystick_id != -1: self._connected = True
def __init__(self, device): """Initializes the device data based on the given device. :param device pyGame joystick object """ self._hardware_id = get_device_guid(device) self._windows_id = sdl2.SDL_JoystickInstanceID(device) name_object = sdl2.SDL_JoystickName(device) if name_object is None: self._name = "Unknown device" logging.getLogger("system").error( "Encountered an invalid device name") else: self._name = name_object.decode("utf-8") self._is_virtual = self._name == "vJoy Device" self._axes = [] for i in range(sdl2.SDL_JoystickNumAxes(device)): self._axes.append((i + 1, i + 1)) self._buttons = sdl2.SDL_JoystickNumButtons(device) self._hats = sdl2.SDL_JoystickNumHats(device) self._vjoy_id = 0
raw_input("\n Press Enter to Quit.") sys.exit(1) for i in range(sdl2.SDL_NumJoysticks()): joy = sdl2.SDL_JoystickOpen(i) if joy is None: print("Joystick device at {} is invalid.".format(i)) else: name_object = sdl2.SDL_JoystickName(joy) if name_object is None: name = "Unknown device" print("Encountered an invalid device name") else: name = name_object.decode("utf-8") hardware_id = struct.unpack(">4I", sdl2.SDL_JoystickGetGUID(joy))[0] windows_id = sdl2.SDL_JoystickInstanceID(joy) hardware_id = struct.unpack(">4I", sdl2.SDL_JoystickGetGUID(joy))[0] windows_id = sdl2.SDL_JoystickInstanceID(joy) axes = sdl2.SDL_JoystickNumAxes(joy) buttons = sdl2.SDL_JoystickNumButtons(joy) hats = sdl2.SDL_JoystickNumHats(joy) joystick = { "Name": name, "Res Name": None, "SCXML ID": None, "JGXML ID": None, "JGPYCON ID": None, "HW ID": hardware_id, "Win ID": windows_id, "Axes": axes,
def joystick_devices_initialization(): """Initializes joystick device information. This function retrieves information about various joystick devices and associates them and collates their information as required. Amongst other things this also ensures that each vJoy device has a correct windows id assigned to it. """ global _joystick_devices, _joystick_init_lock _joystick_init_lock.acquire() syslog = logging.getLogger("system") syslog.info("Initializing joystick devices") syslog.debug("{:d} joysticks detected".format(sdl2.SDL_NumJoysticks())) # Register all devices with the device registry to handle duplicate and # non duplicate devices transparently. devreg = common.DeviceRegistry() devreg.reset() # Register the fake keyboard device devreg.register(0, 0) # Process all connected devices in order to properly initialize the # device registry for i in range(sdl2.SDL_NumJoysticks()): joy = sdl2.SDL_JoystickOpen(i) if joy is None: syslog.error("Invalid joystick device at id {}".format(i)) else: devreg.register(get_device_guid(joy), sdl2.SDL_JoystickInstanceID(joy)) # Process all devices again to detect those that have been added and those # that have been removed since the last time this function ran. # Accumulate all devices devices = [] for i in range(sdl2.SDL_NumJoysticks()): joy = sdl2.SDL_JoystickOpen(i) if joy is not None: devices.append(JoystickDeviceData(joy)) # Compare existing versus observed devices and only proceed if there # is a change to avoid unnecessary work. device_added = False device_removed = False for new_dev in devices: if new_dev not in _joystick_devices: device_added = True syslog.debug( "Added: name={} windows_id={:d} hardware_id={:d}".format( new_dev.name, new_dev.windows_id, new_dev.hardware_id)) for old_dev in _joystick_devices: if old_dev not in devices: device_removed = True syslog.debug( "Removed: name={} windows_id={:d} hardware_id={:d}".format( old_dev.name, old_dev.windows_id, old_dev.hardware_id)) # Terminate if no change occurred if not device_added and not device_removed: _joystick_init_lock.release() return # In order to associate vJoy devices and their ids correctly with SDL # device ids a hash is constructed from the number of axes, buttons, and # hats. This information is used to attempt to find unambiguous mappings # between vJoy and SDL devices. If this is not possible Gremlin will # terminate as this is a non-recoverable error. vjoy_lookup = {} for dev in [dev for dev in devices if dev.is_virtual]: hash_value = (dev.axis_count, dev.buttons, dev.hats) syslog.debug("vJoy windows id {:d}: {}".format(dev.windows_id, hash_value)) # Only unique combinations of axes, buttons, and hats are allowed # for vJoy devices if hash_value in vjoy_lookup: raise error.GremlinError( "Indistinguishable vJoy devices present.\n\n" "vJoy devices have to differ in the number of " "(at least one of) axes, buttons, or hats in order to work " "properly with Joystick Gremlin.") vjoy_lookup[hash_value] = dev # Query all vJoy devices in sequence until all have been processed and # their matching SDL counterparts have been found. vjoy_proxy = VJoyProxy() should_terminate = False for i in range(1, 17): # Only process devices that actually exist if not vjoy.device_exists(i): continue # Compute a hash for the vJoy device and match it against the SDL # device hashes hash_value = (vjoy.axis_count(i), vjoy.button_count(i), vjoy.hat_count(i)) # As we are ensured that no duplicate vJoy devices exist from # the previous step we can directly link the SDL and vJoy device if hash_value in vjoy_lookup: vjoy_lookup[hash_value].set_vjoy_id(i) syslog.debug("vjoy id {:d}: {} - MATCH".format(i, hash_value)) else: should_terminate = True syslog.debug("vjoy id {:d}: {} - ERROR - vJoy device exists " "SDL is missing".format(i, hash_value)) # If the device can be acquired, configure the mapping from # vJoy axis id, which may not be sequential, to the # sequential SDL axis id if hash_value in vjoy_lookup: try: vjoy_dev = vjoy_proxy[i] axis_mapping = [] for j in range(vjoy_dev.axis_count): axis_mapping.append((j + 1, vjoy_dev.axis_id(j + 1))) vjoy_lookup[hash_value].set_axis_mapping(axis_mapping) except error.VJoyError as e: syslog.debug("vJoy id {:} can't be acquired".format(i)) if should_terminate: raise error.GremlinError( "Unable to match vJoy devices to windows devices.") # Reset all devices so we don't hog the ones we aren't actually using vjoy_proxy.reset() # Update device list which will be used when queries for joystick devices # are made _joystick_devices = devices _joystick_init_lock.release()
def dump_input(device): init_sdl() device, name, index, is_game_controller = open_device(device) device_id = sdl2.SDL_JoystickInstanceID(sdl2.SDL_GameControllerGetJoystick(device) if is_game_controller else device) if is_game_controller: controller_name = sdl2.SDL_GameControllerName(device).decode('utf-8') print('Opened game controller, c_name "{}", j_name "{}", idx {}, j_id {}'.format(controller_name, name, index, device_id)) else: print('Opened joystick, j_name "{}", idx {}, j_id {}'.format(name, index, device_id)) def on_joydeviceaddedevent(event): return 'idx: {} j_name: {}'.format(event.jdevice.which, sdl2.SDL_JoystickNameForIndex(event.jdevice.which).decode('utf-8')) def on_joydeviceremovedevent(event): return 'j_id: {}'.format(event.jdevice.which) def on_joyaxismotionevent(event): return 'j_id: {} axis: {} pos: {}'.format(event.jaxis.which, event.jaxis.axis, event.jaxis.value) def on_joyballmotionevent(event): return 'j_id: {} ball: {} xdelta: {} ydelta: {}'.format(event.jball.which, event.jball.ball, event.jball.xrel, event.jball.yrel) def on_joyhatmotionevent(event): return 'j_id: {} hat: {} pos: {}'.format(event.jhat.which, event.jhat.hat, SDL_HAT_DIRECTION_NAMES.get(event.jhat.value, event.jhat.value)) def on_joybuttonevent(event): return 'j_id: {} button: {} state: {}'.format( event.jbutton.which, event.jbutton.button, 'is_pressed' if bool(event.jbutton.state) else 'is_not_pressed' ) def on_controllerdeviceaddedevent(event): return 'idx: {} c_name: {}'.format(event.cdevice.which, sdl2.SDL_GameControllerNameForIndex(event.cdevice.which).decode('utf-8')) def on_controllerdeviceremovedevent(event): return 'c_id: {}'.format(event.cdevice.which) def on_controlleraxismotionevent(event): return 'c_id: {} axis: {} pos: {}'.format( event.caxis.which, SDL_CONTROLLER_AXIS_NAMES.get(event.caxis.axis, event.caxis.axis), event.caxis.value ) def on_controllerbuttonevent(event): return 'c_id: {} button: {} state: {}'.format( event.cbutton.which, SDL_CONTROLLER_BUTTON_NAMES.get(event.cbutton.button, event.cbutton.button), 'is_pressed' if bool(event.cbutton.state) else 'is_not_pressed' ) event_handlers = { sdl2.SDL_JOYDEVICEADDED: on_joydeviceaddedevent, sdl2.SDL_JOYDEVICEREMOVED: on_joydeviceremovedevent, sdl2.SDL_JOYAXISMOTION: on_joyaxismotionevent, sdl2.SDL_JOYBALLMOTION: on_joyballmotionevent, sdl2.SDL_JOYHATMOTION: on_joyhatmotionevent, sdl2.SDL_JOYBUTTONDOWN: on_joybuttonevent, sdl2.SDL_JOYBUTTONUP: on_joybuttonevent, sdl2.SDL_CONTROLLERDEVICEADDED: on_controllerdeviceaddedevent, sdl2.SDL_CONTROLLERDEVICEREMOVED: on_controllerdeviceremovedevent, sdl2.SDL_CONTROLLERAXISMOTION: on_controlleraxismotionevent, sdl2.SDL_CONTROLLERBUTTONDOWN: on_controllerbuttonevent, sdl2.SDL_CONTROLLERBUTTONUP: on_controllerbuttonevent } print('# milliseconds since SDL initialization, SDL_EventType, some event-type-specific information (not necessarily exhaustive)') try: while 1: event = sdl2.SDL_Event() # If there is no event for an entire second, we iterate, giving CPython an opportunity to # raise KeyboardInterrupt. if sdl2.SDL_WaitEventTimeout(ctypes.byref(event), 1000): if hasattr(event, 'generic'): s = '{}, {}'.format(event.generic.timestamp, SDL_EVENT_NAMES.get(event.type, "UNKNOWN")) else: s = '{}, {}'.format(event.common.timestamp, SDL_EVENT_NAMES.get(event.type, "UNKNOWN")) try: s += ', {}'.format(event_handlers[event.type](event)) except KeyError: pass print(s) if event.type == sdl2.SDL_QUIT: print('# SDL_QUIT received. Exiting dump_input(..) ...') break if event.type == sdl2.SDL_JOYDEVICEREMOVED and event.jdevice.which == device_id: print('# Our SDL input device has been disconnected. Exiting dump_input(..) ...') break except KeyboardInterrupt: print('\n# ctrl-c received. Exiting dump_input(..) ...')
def __new__(cls, identifier=None, instance_id=None, *args, **kwargs): # Check init if not get_init(): init() # Create the object joy = super().__new__(cls) if instance_id is not None: # Create the underlying joystick from the instance id. # SDL_JOYDEVICEREMOVED and all other SDL_JOY#### events give the instance id joy.joystick = sdl2.SDL_JoystickFromInstanceID(instance_id) # print('Instance ID:', raw_joystick, SDL_JoystickGetAttached(raw_joystick)) else: # Create the underlying joystick from the enumerated identifier # SDL_JOYDEVICEADDED and SDL_NumJoysticks use open if identifier is None: identifier = 0 if isinstance(identifier, str): # Get the joystick from the name or None if not found! for i in range(sdl2.SDL_NumJoysticks()): raw_joystick = sdl2.SDL_JoystickOpen(i) try: if sdl2.SDL_JoystickName(raw_joystick).decode( 'utf-8') == identifier: joy.joystick = raw_joystick break except: pass else: joy.joystick = sdl2.SDL_JoystickOpen(identifier) # print('ID:', raw_joystick, SDL_JoystickGetAttached(raw_joystick)) try: joy.identifier = sdl2.SDL_JoystickID( sdl2.SDL_JoystickInstanceID(joy.joystick)).value # joy.identifier = SDL_JoystickInstanceID(raw_joystick) joy.name = sdl2.SDL_JoystickName(joy.joystick).decode('utf-8') joy.numaxes = sdl2.SDL_JoystickNumAxes(joy.joystick) joy.numbuttons = sdl2.SDL_JoystickNumButtons(joy.joystick) joy.numhats = sdl2.SDL_JoystickNumHats(joy.joystick) joy.numballs = sdl2.SDL_JoystickNumBalls(joy.joystick) joy.init_keys() except: pass # Try to get the gamepad object try: joy.gamecontroller = sdl2.SDL_GameControllerOpen(joy.identifier) # FromInstanceId does not Attach! # joy.gamecontroller = SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(joy.joystick) # print('ID:', SDL_GameControllerGetAttached(joy.gamecontroller)) except: joy.gamecontroller = None try: joy.guid = get_guid( joy.joystick ) # Using this is more reliable for the GameController stuff except: pass return joy
def __init__( self, input_device_index=0, input_device_name=None, scope_server_host='127.0.0.1', zmq_context=None, maximum_portion_of_wallclock_time_allowed_for_axis_commands=DEFAULT_MAX_AXIS_COMMAND_WALLCLOCK_TIME_PORTION, maximum_axis_command_cool_off=DEFAULT_MAX_AXIS_COMMAND_COOL_OFF, warnings_enabled=False): """* input_device_index: The argument passed to SDL_JoystickOpen(index) or SDL_GameControllerOpen(index). Ignored if the value of input_device_name is not None. * input_device_name: If specified, input_device_name should be the exact string or UTF8-encoded bytearray by which SDL identifies the controller you wish to use, as reported by SDL_JoystickName(..). For USB devices, this is USB iManufacturer + ' ' + iProduct. (See example below.) * scope_server_host: IP address or hostname of scope server. * zmq_context: If None, one is created. * maximum_portion_of_wallclock_time_allowed_for_axis_commands: Limit the rate at which commands are sent to the scope in response to controller axis motion such that the scope such that the scope is busy processing those commands no more than this fraction of the time. * maximum_axis_command_cool_off: The maximum number of milliseconds to defer issuance of scope commands in response to controller axis motion (in order to enforce maximum_portion_of_wallclock_time_allowed_for_axis_commands). For example, a Sony PS4 controller with the following lsusb -v output would be known to SDL as 'Sony Computer Entertainment Wireless Controller': Bus 003 Device 041: ID 054c:05c4 Sony Corp. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x054c Sony Corp. idProduct 0x05c4 bcdDevice 1.00 iManufacturer 1 Sony Computer Entertainment iProduct 2 Wireless Controller iSerial 0 bNumConfigurations 1 ... Additionally, sdl_control.enumerate_devices(), a module function, returns a list of the currently available SDL joystick and game controller input devices, in the order by which SDL knows them. So, if you know that your input device is a Logilech something-or-other, and sdl_control.enumerate_devices() returns the following: [ 'Nintenbo Olympic Sport Mat v3.5', 'MANUFACTURER NAME HERE. DONT FORGET TO SET THIS!! Many Product Ltd. 1132 Guangzhou $ !*llSN9_Q ', 'Duckhunt Defender Scanline-Detecting Plastic Gun That Sadly Does Not Work With LCDs', 'Macrosoft ZBox-720 Controller Colossal-Hands Mondo Edition', 'Logilech SixThousandAxis KiloButtonPad With Haptic Feedback Explosion', 'Gametech Gameseries MegaGamer Excel Spreadsheet 3D-Orb For Executives, Doom3D Edition', 'Gametech Gameseries MegaGamer Excel Spreadsheet 3D-Orb For Light Rail Transport, Doom3D Edition' ] You will therefore want to specify input_device_index=4 or input_device_name='Logilech SixThousandAxis KiloButtonPad With Haptic Feedback Explosion' """ assert 0 < maximum_portion_of_wallclock_time_allowed_for_axis_commands <= 1 init_sdl() self.device, self.device_is_game_controller = open_device( input_device_index, input_device_name) if self.device_is_game_controller: self.jdevice = sdl2.SDL_GameControllerGetJoystick(self.device) else: self.jdevice = self.device self.device_id = sdl2.SDL_JoystickInstanceID(self.jdevice) self.num_axes = sdl2.SDL_JoystickNumAxes(self.jdevice) self.num_buttons = sdl2.SDL_JoystickNumButtons(self.jdevice) self.num_hats = sdl2.SDL_JoystickNumHats(self.jdevice) self.warnings_enabled = warnings_enabled if warnings_enabled: print('JoypadInput is connecting to scope server...', file=sys.stderr) self.scope, self.scope_properties = scope_client.client_main( scope_server_host, zmq_context) if warnings_enabled: print('JoypadInput successfully connected to scope server.', file=sys.stderr) self.event_loop_is_running = False self.quit_event_posted = False self.throttle_delay_command_time_ratio = 1 - maximum_portion_of_wallclock_time_allowed_for_axis_commands self.throttle_delay_command_time_ratio /= maximum_portion_of_wallclock_time_allowed_for_axis_commands self.maximum_axis_command_cool_off = maximum_axis_command_cool_off self._axes_throttle_delay_lock = threading.Lock() self._c_on_axes_throttle_delay_expired_timer_callback = SDL_TIMER_CALLBACK_TYPE( self._on_axes_throttle_delay_expired_timer_callback) self.handle_button_callback = self.default_handle_button_callback
def poll_sdl_events(self): import ctypes as c sdl.SDL_JoystickEventState(sdl.SDL_ENABLE) self.num_gamepads = sdl.SDL_NumJoysticks() self.active_gamepads = {} while self.pending: event = sdl.SDL_Event() while sdl.SDL_PollEvent(c.byref(event)): if event.type == sdl.SDL_JOYBUTTONDOWN: button = event.jbutton self.gamepad_input = button.which self.gamepad_pressed = button.button self.gamepad_type = "button" elif event.type == sdl.SDL_JOYAXISMOTION: axis = event.jaxis if event.jaxis.value < -16000: self.gamepad_input = axis.which self.gamepad_pressed = axis.axis self.gamepad_type = "Naxis" elif event.jaxis.value > 16000: self.gamepad_input = axis.which self.gamepad_pressed = axis.axis self.gamepad_type = "Paxis" elif event.type == sdl.SDL_JOYDEVICEADDED: n = event.jdevice.which device = sdl.SDL_JoystickOpen(n) joy_id = sdl.SDL_JoystickInstanceID(device) self.active_gamepads[joy_id] = device name = sdl.SDL_JoystickName(device).decode("utf-8") page = 1 while page < 5: self.pages_list[page][1].insert( n, str(n), str(n) + ": " + name) if self.gamepads_stored[page][1] == name: self.pages_list[page][1].set_active_id( str(self.gamepads_stored[page][0])) page += 1 log.info(f"Controller added: {name}") log.info( f"Current active controllers: {sdl.SDL_NumJoysticks()}" ) elif event.type == sdl.SDL_JOYDEVICEREMOVED: joy_id = event.jdevice.which device = self.active_gamepads[joy_id] if sdl.SDL_JoystickGetAttached(device): sdl.SDL_JoystickClose(device) name = sdl.SDL_JoystickName(device).decode("utf-8") page = 1 while page < 5: if self.gamepads_stored[page][1] == name: self.pages_list[page][1].set_active_id("-1") self.pages_list[page][1].remove( self.gamepads_stored[page][0]) page += 1 log.info(f"Controller removed: {name}") self.active_gamepads.pop(joy_id) log.info( f"Current active controllers: {sdl.SDL_NumJoysticks()}" )