def stop(self): """Stops listening to events and unloads all callbacks.""" # Disconnect all signals if self._running: evt_lst = event_handler.EventListener() kb = input_devices.Keyboard() evt_lst.keyboard_event.disconnect(self.event_handler.process_event) evt_lst.joystick_event.disconnect(self.event_handler.process_event) evt_lst.keyboard_event.disconnect(kb.keyboard_event) self.event_handler.mode_changed.disconnect( self._vjoy_curves.mode_changed) self._running = False # Empty callback registry input_devices.callback_registry.clear() self.event_handler.clear() # Stop periodic events and clear registry input_devices.periodic_registry.stop() input_devices.periodic_registry.clear() macro.MacroManager().stop() # Remove all claims on VJoy devices joystick_handling.VJoyProxy.reset()
def start(self, inheritance_tree, settings, start_mode, profile): """Starts listening to events and loads all existing callbacks. :param inheritance_tree tree encoding inheritance between the different modes :param settings profile settings to apply at launch :param start_mode the mode in which to start Gremlin :param profile the profile to use when generating all the callbacks """ # Reset states to their default values self._inheritance_tree = inheritance_tree self._reset_state() # Check if we want to override the star mode as determined by the # heuristic if settings.startup_mode is not None: if settings.startup_mode in gremlin.profile.mode_list(profile): start_mode = settings.startup_mode # Load the generated code try: # Load generated python code gremlin_code = util.load_module("gremlin_code") # Create callbacks fom the user code callback_count = 0 for dev_id, modes in input_devices.callback_registry.registry.items( ): for mode, callbacks in modes.items(): for event, callback_list in callbacks.items(): for callback in callback_list.values(): self.event_handler.add_callback( dev_id, mode, event, callback[0], callback[1]) callback_count += 1 # Create input callbacks based on the profile's content for device in profile.devices.values(): hid = device.hardware_id wid = device.windows_id dev_id = util.get_device_id(hid, wid) for mode in device.modes.values(): for input_items in mode.config.values(): for input_item in input_items.values(): # Only add callbacks for input items that actually # contain actions if len(input_item.containers) == 0: continue event = event_handler.Event( event_type=input_item.input_type, hardware_id=hid, windows_id=wid, identifier=input_item.input_id) self.event_handler.add_callback( dev_id, mode.name, event, InputItemCallback(input_item), input_item.always_execute) # Create merge axis callbacks for entry in profile.merge_axes: merge_axis = MergeAxis(entry["vjoy"]["device_id"], entry["vjoy"]["axis_id"]) self._merge_axes.append(merge_axis) # Lower axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, hardware_id=entry["lower"]["hardware_id"], windows_id=entry["lower"]["windows_id"], identifier=entry["lower"]["axis_id"]) self.event_handler.add_callback( util.get_device_id(entry["lower"]["hardware_id"], entry["lower"]["windows_id"]), entry["mode"], event, merge_axis.update_axis1, False) # Upper axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, hardware_id=entry["upper"]["hardware_id"], windows_id=entry["upper"]["windows_id"], identifier=entry["upper"]["axis_id"]) self.event_handler.add_callback( util.get_device_id(entry["upper"]["hardware_id"], entry["upper"]["windows_id"]), entry["mode"], event, merge_axis.update_axis2, False) # Create vJoy response curve setups self._vjoy_curves.profile_data = profile.vjoy_devices self.event_handler.mode_changed.connect( self._vjoy_curves.mode_changed) # Use inheritance to build input action lookup table self.event_handler.build_event_lookup(inheritance_tree) # Set vJoy axis default values for vid, data in settings.vjoy_initial_values.items(): vjoy_proxy = joystick_handling.VJoyProxy()[vid] for aid, value in data.items(): vjoy_proxy.axis(aid).set_absolute_value(value) # Connect signals evt_listener = event_handler.EventListener() kb = input_devices.Keyboard() evt_listener.keyboard_event.connect( self.event_handler.process_event) evt_listener.joystick_event.connect( self.event_handler.process_event) evt_listener.keyboard_event.connect(kb.keyboard_event) input_devices.periodic_registry.start() macro.MacroManager().start() self.event_handler.change_mode(start_mode) self.event_handler.resume() self._running = True except ImportError as e: util.display_error( "Unable to launch due to missing custom modules: {}".format( str(e)))
def start(self, inheritance_tree, settings, start_mode, profile): """Starts listening to events and loads all existing callbacks. :param inheritance_tree tree encoding inheritance between the different modes :param settings profile settings to apply at launch :param start_mode the mode in which to start Gremlin :param profile the profile to use when generating all the callbacks """ # Reset states to their default values self._inheritance_tree = inheritance_tree self._reset_state() # Check if we want to override the start mode as determined by the # heuristic if settings.startup_mode is not None: if settings.startup_mode in gremlin.profile.mode_list(profile): start_mode = settings.startup_mode # Set default macro action delay gremlin.macro.MacroManager().default_delay = settings.default_delay # Retrieve list of current paths searched by Python system_paths = [os.path.normcase(os.path.abspath(p)) for p in sys.path] # Load the generated code try: # Populate custom module variable registry var_reg = user_plugin.variable_registry for plugin in profile.plugins: # Perform system path mangling for import statements path, _ = os.path.split( os.path.normcase(os.path.abspath(plugin.file_name)) ) if path not in system_paths: system_paths.append(path) # Load module specification so we can later create multiple # instances if desired spec = importlib.util.spec_from_file_location( "".join(random.choices(string.ascii_lowercase, k=16)), plugin.file_name ) # Process each instance in turn for instance in plugin.instances: # Skip all instances that are not fully configured if not instance.is_configured(): continue # Store variable values in the registry for var in instance.variables.values(): var_reg.set( plugin.file_name, instance.name, var.name, var.value ) # Load the modules tmp = importlib.util.module_from_spec(spec) tmp.__gremlin_identifier = (plugin.file_name, instance.name) spec.loader.exec_module(tmp) # Update system path list searched by Python sys.path = system_paths # Create callbacks fom the user code callback_count = 0 for dev_id, modes in input_devices.callback_registry.registry.items(): for mode, events in modes.items(): for event, callback_list in events.items(): for callback in callback_list.values(): self.event_handler.add_callback( dev_id, mode, event, callback[0], callback[1] ) callback_count += 1 # Add a fake keyboard action which does nothing to the callbacks # in every mode in order to have empty modes be "present" for mode_name in gremlin.profile.mode_list(profile): self.event_handler.add_callback( 0, mode_name, None, lambda x: x, False ) # Create input callbacks based on the profile's content for device in profile.devices.values(): for mode in device.modes.values(): for input_items in mode.config.values(): for input_item in input_items.values(): # Only add callbacks for input items that actually # contain actions if len(input_item.containers) == 0: continue event = event_handler.Event( event_type=input_item.input_type, device_guid=device.device_guid, identifier=input_item.input_id ) # Create possibly several callbacks depending # on the input item's content callbacks = [] for container in input_item.containers: if not container.is_valid(): logging.getLogger("system").warning( "Incomplete container ignored" ) continue callbacks.extend(container.generate_callbacks()) for cb_data in callbacks: if cb_data.event is None: self.event_handler.add_callback( device.device_guid, mode.name, event, cb_data.callback, input_item.always_execute ) else: self.event_handler.add_callback( dill.GUID_Virtual, mode.name, cb_data.event, cb_data.callback, input_item.always_execute ) # Create merge axis callbacks for entry in profile.merge_axes: merge_axis = MergeAxis( entry["vjoy"]["vjoy_id"], entry["vjoy"]["axis_id"], entry["operation"] ) self._merge_axes.append(merge_axis) # Lower axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, device_guid=entry["lower"]["device_guid"], identifier=entry["lower"]["axis_id"] ) self.event_handler.add_callback( event.device_guid, entry["mode"], event, merge_axis.update_axis1, False ) # Upper axis callback event = event_handler.Event( event_type=gremlin.common.InputType.JoystickAxis, device_guid=entry["upper"]["device_guid"], identifier=entry["upper"]["axis_id"] ) self.event_handler.add_callback( event.device_guid, entry["mode"], event, merge_axis.update_axis2, False ) # Create vJoy response curve setups self._vjoy_curves.profile_data = profile.vjoy_devices self.event_handler.mode_changed.connect( self._vjoy_curves.mode_changed ) # Use inheritance to build input action lookup table self.event_handler.build_event_lookup(inheritance_tree) # Set vJoy axis default values for vid, data in settings.vjoy_initial_values.items(): vjoy_proxy = joystick_handling.VJoyProxy()[vid] for aid, value in data.items(): vjoy_proxy.axis(linear_index=aid).set_absolute_value(value) # Connect signals evt_listener = event_handler.EventListener() kb = input_devices.Keyboard() evt_listener.keyboard_event.connect( self.event_handler.process_event ) evt_listener.joystick_event.connect( self.event_handler.process_event ) evt_listener.virtual_event.connect( self.event_handler.process_event ) evt_listener.keyboard_event.connect(kb.keyboard_event) evt_listener.gremlin_active = True input_devices.periodic_registry.start() macro.MacroManager().start() self.event_handler.change_mode(start_mode) self.event_handler.resume() self._running = True sendinput.MouseController().start() except ImportError as e: util.display_error( "Unable to launch due to missing user plugin: {}" .format(str(e)) )