def _sm_end_session(self, flags): if self._is_monitor_session(): logger.info("Ending session") def e(): self.stop() self._sm_client_dbus_will_quit(True, "") g15scheduler.queue(SERVICE_QUEUE, "endSession", 0.0, e)
def _active_session_changed(self, object_path): logger.debug("Adding seat %s", object_path) if self._is_monitor_session(): self.session_active = object_path == self.this_session_path if self.session_active: logger.info("g15-desktop service is running on the active session") else: logger.info("g15-desktop service is NOT running on the active session") g15scheduler.queue(SERVICE_QUEUE, "activeSessionChanged", 0.0, self._check_state_of_all_devices)
def _logind_seat0_property_changed(self, interface, dicto, properties): if "ActiveSession" in properties: if self._is_monitor_session(): session_path = self._get_systemd_active_session_path() logger.info("This session %s", session_path) self.session_active = session_path == self.this_session_path if self.session_active: logger.info("g15-desktop service is running on the active session") else: logger.info("g15-desktop service is NOT running on the active session") g15scheduler.queue(SERVICE_QUEUE, "activeSessionChanged", 0.0, self._check_state_of_all_devices)
def handle_macro(self, macro): """ We want to return control immediately after asking for a macro to be handled, but we only ever want one macro running at a time. This means the macro action is put on it's own queue. This also allows long running macros to be cancelled Keyword arguments: macro -- macro to handle """ g15scheduler.queue(MACRO_HANDLER_QUEUE, "HandleMacro", 0, self._do_handle, macro)
def _handle_macro(self, macro, state, key_states, repetition=False): self._consume_keys(key_states) delay = macro.repeat_delay if macro.repeat_delay != -1 else 0.1 if macro.repeat_mode == g15profile.REPEAT_TOGGLE and state == g15driver.KEY_STATE_UP: if macro in self.__repeat_macros and not repetition: # Key pressed again, so stop repeating self.__cancel_macro_repeat_timer() self.__repeat_macros.remove(macro) else: if not macro in self.__repeat_macros and not repetition: self.__repeat_macros.append(macro) else: self._process_macro(macro, state, key_states) # We test again because a toggle might have stopped the repeat if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "RepeatMacro", delay, self._handle_macro, macro, state, key_states, True ) elif macro.repeat_mode == g15profile.REPEAT_WHILE_HELD and not state == g15driver.KEY_STATE_DOWN: if state == g15driver.KEY_STATE_UP and macro in self.__repeat_macros and not repetition: # Key released again, so stop repeating self.__cancel_macro_repeat_timer() self.__repeat_macros.remove(macro) else: if state == g15driver.KEY_STATE_HELD and not macro in self.__repeat_macros and not repetition: self.__repeat_macros.append(macro) self._process_macro(macro, state, key_states) # We test again because a toggle might have stopped the repeat if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "RepeatMacro", delay, self._handle_macro, macro, g15driver.KEY_STATE_HELD, key_states, True, ) elif state == g15driver.KEY_STATE_DOWN and macro.activate_on == g15driver.KEY_STATE_DOWN: self._process_macro(macro, state, key_states) elif state == g15driver.KEY_STATE_UP and macro.activate_on == g15driver.KEY_STATE_UP: self._process_macro(macro, state, key_states) elif state == g15driver.KEY_STATE_HELD and macro.activate_on == g15driver.KEY_STATE_HELD: self._process_macro(macro, state, key_states) # Also defeat the key release so any normal KEY_STATE_UP macros don't get activated as well self._defeat_release(key_states)
def acquire_control(self, control, release_after = None, val = None, on_release = None): control_acquisitions = self.acquired_controls[control.id] if control.id in self.acquired_controls else [] self.acquired_controls[control.id] = control_acquisitions if len(control_acquisitions) == 0: self.initial_acquired_control_values[control.id] = control.value control_acquisition = ControlAcquisition(self, control) control_acquisition.on_release = on_release control_acquisitions.append(control_acquisition) # Only set the value when active (i.e. in the control_acquisitions list) control_acquisition.set_value(val if val is not None else control.value) if release_after: g15scheduler.queue(FX_QUEUE, "ReleaseControl", release_after, self._release_control, control_acquisition) return control_acquisition
def acquire_control(self, control, release_after=None, val=None, on_release=None): control_acquisitions = self.acquired_controls[control.id] if control.id in self.acquired_controls else [] self.acquired_controls[control.id] = control_acquisitions if len(control_acquisitions) == 0: self.initial_acquired_control_values[control.id] = control.value control_acquisition = ControlAcquisition(self, control) control_acquisition.on_release = on_release control_acquisitions.append(control_acquisition) # Only set the value when active (i.e. in the control_acquisitions list) control_acquisition.set_value(val if val is not None else control.value) if release_after: g15scheduler.queue(FX_QUEUE, "ReleaseControl", release_after, self._release_control, control_acquisition) return control_acquisition
def _reduce(self, interval, target_val, release, step): if not self.fade_cancelled: if isinstance(self.val, int): AbstractControlAcquisition._reduce(self, interval, target_val, release, step) else: if self.val > target_val: h, s, v = self.rgb_to_hsv(self.val) v = max(0, v - step) new_rgb = self.hsv_to_rgb((h, s, v)) if new_rgb == self.val: new_rgb = target_val self.set_value(new_rgb) if self.val <= target_val: if release and not self._released: self.driver.release_control(self) else: g15scheduler.queue(FX_QUEUE, "Fade", interval, self._reduce, interval, target_val, release, step)
def _repeat_uinput(self, macro, uc, uinput_repeat=False): if macro in self.__repeat_macros: self._send_uinput_keypress(macro, uc, uinput_repeat) if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "MacroRepeat", macro.repeat_delay, self._repeat_uinput, self._reload_macro_instance(macro), uc, uinput_repeat)
def _reduce(self, interval, target_val, release, step): if not self.fade_cancelled: if self.val > target_val: self.set_value(self.val - step) if self.val == target_val: if release: self.driver.release_control(self) else: self.fade_timer = g15scheduler.queue(FX_QUEUE, "Fade", interval, self._reduce, interval, target_val, release, step)
def _handle_macro(self, macro, state, key_states, repetition=False): self._consume_keys(key_states) delay = macro.repeat_delay if macro.repeat_delay != -1 else 0.1 if macro.repeat_mode == g15profile.REPEAT_TOGGLE and state == g15driver.KEY_STATE_UP: if macro in self.__repeat_macros and not repetition: # Key pressed again, so stop repeating self.__cancel_macro_repeat_timer() self.__repeat_macros.remove(macro) else: if not macro in self.__repeat_macros and not repetition: self.__repeat_macros.append(macro) else: self._process_macro(macro, state, key_states) # We test again because a toggle might have stopped the repeat if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "RepeatMacro", delay, self._handle_macro, macro, state, key_states, True) elif macro.repeat_mode == g15profile.REPEAT_WHILE_HELD and not state == g15driver.KEY_STATE_DOWN: if state == g15driver.KEY_STATE_UP and macro in self.__repeat_macros and not repetition: # Key released again, so stop repeating self.__cancel_macro_repeat_timer() self.__repeat_macros.remove(macro) else: if state == g15driver.KEY_STATE_HELD and not macro in self.__repeat_macros and not repetition: self.__repeat_macros.append(macro) self._process_macro(macro, state, key_states) # We test again because a toggle might have stopped the repeat if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "RepeatMacro", delay, self._handle_macro, macro, g15driver.KEY_STATE_HELD, key_states, True) elif state == g15driver.KEY_STATE_DOWN and macro.activate_on == g15driver.KEY_STATE_DOWN: self._process_macro(macro, state, key_states) elif state == g15driver.KEY_STATE_UP and macro.activate_on == g15driver.KEY_STATE_UP: self._process_macro(macro, state, key_states) elif state == g15driver.KEY_STATE_HELD and macro.activate_on == g15driver.KEY_STATE_HELD: self._process_macro(macro, state, key_states) # Also defeat the key release so any normal KEY_STATE_UP macros don't get activated as well self._defeat_release(key_states)
def blink(self, off_val = 0, delay = 0.5, duration = None, blink_started = None): if blink_started == None: blink_started = time.time() self.cancel_fade() self.cancel_reset() if self.on: self.adjust(self.val) else: self.adjust(off_val if isinstance(off_val, int) or isinstance(off_val, tuple) else off_val()) self.on = not self.on if duration == None or time.time() < blink_started + duration: self.reset_timer = g15scheduler.queue(FX_QUEUE, "Blink", delay, self.blink, off_val, delay, duration, blink_started) return self.reset_timer
def _repeat_uinput(self, macro, uc, uinput_repeat=False): if macro in self.__repeat_macros: self._send_uinput_keypress(macro, uc, uinput_repeat) if macro in self.__repeat_macros: self.__macro_repeat_timer = g15scheduler.queue( self.queue_name, "MacroRepeat", macro.repeat_delay, self._repeat_uinput, self._reload_macro_instance(macro), uc, uinput_repeat, )
def _configure_key_state(self, key, state_id): """ Maintains the "key state" table, which holds what state each key is currently in. This function will return the number of state changes, so this key event may be ignored if it is no longer appropriate (i.e. a hold timer event for keys that are now released) Keyword arguments: key -- single key state_id -- state_id (g15driver.KEY_STATE_UP, _DOWN or _HELD) """ if state_id == g15driver.KEY_STATE_HELD and not key in self.__key_states: """ All keys were released before the HOLD timer kicked in, so we totally ignore this key """ pass else: if not key in self.__key_states: self.__key_states[key] = KeyState(key) key_state = self.__key_states[key] # This is a new key press, so reset this key's consumed state key_state.consumed = False # Check the sanity of the key press self._check_key_state(state_id, key_state) key_state.state_id = state_id if state_id == g15driver.KEY_STATE_DOWN: """ Key is now down, let's set up a timer to produce a held event """ key_state.timer = g15scheduler.queue( self.queue_name, "HoldKey%s" % str(key), self.__screen.service.key_hold_duration, self._do_key_received, [key], g15driver.KEY_STATE_HELD, ) elif state_id == g15driver.KEY_STATE_UP: """ Now the key is up, cancel the HELD timer if one exists. """ key_state.cancel_timer() return True
def blink(self, off_val=0, delay=0.5, duration=None, blink_started=None): if blink_started is None: blink_started = time.time() self.cancel_fade() self.cancel_reset() if self.on: self.adjust(self.val) else: self.adjust(off_val if isinstance(off_val, int) or isinstance(off_val, tuple) else off_val()) self.on = not self.on if duration is None or time.time() < blink_started + duration: self.reset_timer = g15scheduler.queue(FX_QUEUE, "Blink", delay, self.blink, off_val, delay, duration, blink_started) return self.reset_timer
def _handle_uinput_macros(self): """ Search for all the uinput macros that would be activated by the current key state, and emit events of the same type. """ uinput_repeat = False for m in self.__uinput_macros: down = [] up = [] held = [] for k in m.keys: if k in self.__key_states: key_state = self.__key_states[k] if not key_state.is_consumed(): if key_state.state_id == g15driver.KEY_STATE_UP and not key_state.defeat_release: up.append(key_state) if key_state.state_id == g15driver.KEY_STATE_DOWN: down.append(key_state) if key_state.state_id == g15driver.KEY_STATE_HELD: held.append(key_state) if len(down) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_DOWN, down) if len(up) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_UP, up) if len(held) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_HELD, held) uinput_repeat = True """ Simulate a uinput repeat by just handling an empty key list. No keys have changed state, so we should just keep hitting this reschedule until they do """ if uinput_repeat: g15scheduler.queue(self.queue_name, "RepeatUinput", \ 0.1, \ self._handle_uinput_macros)
def _handle_uinput_macros(self): """ Search for all the uinput macros that would be activated by the current key state, and emit events of the same type. """ uinput_repeat = False for m in self.__uinput_macros: down = [] up = [] held = [] for k in m.keys: if k in self.__key_states: key_state = self.__key_states[k] if not key_state.is_consumed(): if key_state.state_id == g15driver.KEY_STATE_UP and not key_state.defeat_release: up.append(key_state) if key_state.state_id == g15driver.KEY_STATE_DOWN: down.append(key_state) if key_state.state_id == g15driver.KEY_STATE_HELD: held.append(key_state) if len(down) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_DOWN, down) if len(up) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_UP, up) if len(held) == len(m.keys): self._handle_uinput_macro(m, g15driver.KEY_STATE_HELD, held) uinput_repeat = True """ Simulate a uinput repeat by just handling an empty key list. No keys have changed state, so we should just keep hitting this reschedule until they do """ if uinput_repeat: g15scheduler.queue(self.queue_name, "RepeatUinput", 0.1, self._handle_uinput_macros)
def _configure_key_state(self, key, state_id): """ Maintains the "key state" table, which holds what state each key is currently in. This function will return the number of state changes, so this key event may be ignored if it is no longer appropriate (i.e. a hold timer event for keys that are now released) Keyword arguments: key -- single key state_id -- state_id (g15driver.KEY_STATE_UP, _DOWN or _HELD) """ if state_id == g15driver.KEY_STATE_HELD and not key in self.__key_states: """ All keys were released before the HOLD timer kicked in, so we totally ignore this key """ pass else: if not key in self.__key_states: self.__key_states[key] = KeyState(key) key_state = self.__key_states[key] # This is a new key press, so reset this key's consumed state key_state.consumed = False # Check the sanity of the key press self._check_key_state(state_id, key_state) key_state.state_id = state_id if state_id == g15driver.KEY_STATE_DOWN: """ Key is now down, let's set up a timer to produce a held event """ key_state.timer = g15scheduler.queue(self.queue_name, "HoldKey%s" % str(key), \ self.__screen.service.key_hold_duration, \ self._do_key_received, [ key ], \ g15driver.KEY_STATE_HELD) elif state_id == g15driver.KEY_STATE_UP: """ Now the key is up, cancel the HELD timer if one exists. """ key_state.cancel_timer() return True
def set_value(self, val, reset_after=None): old_val = val if self.val is None or val != self.val or reset_after is not None: if self.val is None: logger.debug("Initial value of control is %s", str(val)) self.reset_val = val self.val = val self.on = True self.cancel_fade() self.adjust(val) self.cancel_reset() logger.debug("Set value of control to %s", str(val)) if reset_after: self.reset_val = old_val self.reset_timer = g15scheduler.queue(FX_QUEUE, "LEDReset", reset_after, self.reset) return self.reset_timer
def set_value(self, val, reset_after = None): old_val = val if self.val is None or val != self.val or reset_after is not None: if self.val is None: logger.debug("Initial value of control is %s", str(val)) self.reset_val = val self.val = val self.on = True self.cancel_fade() self.adjust(val) self.cancel_reset() logger.debug("Set value of control to %s", str(val)) if reset_after: self.reset_val = old_val self.reset_timer = g15scheduler.queue(FX_QUEUE, "LEDReset", reset_after, self.reset) return self.reset_timer
def Stop(self): g15scheduler.queue("serviceQueue", "dbusShutdown", 0, self._service.shutdown)
def _device_enabled_configuration_changed(self, client, connection_id, entry, device): g15scheduler.queue(SERVICE_QUEUE, "deviceStateChanged", 0, self._check_device_state, device)
def handle_key(self, keys, state_id, post): """ Handle raw keys. We use this to complete any macros waiting for another key events """ g15scheduler.queue(MACRO_HANDLER_QUEUE, "HandleMacro", 0, self._do_handle_key, keys, state_id, post)