Exemple #1
0
  def __init__(self, ioloop, cb, types = ["kbd", "mouse", "js"]):
    self.ioloop = ioloop
    self.cb = cb
    self.streams = []
    self.handler = EventHandler()
    self.types = types

    devs = list(find_devices(types))
    for index, type in devs:
      self.add_stream(index, type)

    self.udevCtx = pyudev.Context()
    self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx)
    self.udevMon.filter_by(subsystem = 'input')
    self.udevMon.start()
    ioloop.add_handler(self.udevMon.fileno(), self.udev_handler, ioloop.READ)
    def __init__(self, ioloop, cb, types='kbd mouse js'.split(), log=None):
        self.ioloop = ioloop
        self.cb = cb
        self.streams = []
        self.handler = EventHandler()
        self.types = types
        self.log = log if log else logging.getLogger('inevent')

        self.udevCtx = pyudev.Context()
        self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx)
        self.udevMon.filter_by(subsystem='input')

        devs = list(self.find_devices(types))
        for index, type, name in devs:
            self.add_stream(index, type, name)

        self.udevMon.start()
        ioloop.add_handler(self.udevMon.fileno(), self.udev_handler,
                           ioloop.READ)
Exemple #3
0
class InEvent(object):
  """Encapsulates the entire InEvent subsystem.

  This is generally all you need to import.

  On instantiation, we open all devices that are keyboards, mice or joysticks.
  That means we might have two of one sort of another, and that might be a
  problem, but it would be rather rare.

  There are several ABS (joystick, touch) events that we do not handle,
  specifically THROTTLE, RUDDER, WHEEL, GAS, BRAKE, HAT1, HAT2, HAT3, PRESSURE,
  DISTANCE, TILT, TOOL_WIDTH. Implementing these is left as an exercise
  for the interested reader. Similarly, we make no attempt to handle
  multi-touch.

  Handlers can be supplied, in which case they are called for each event, but
  it isn't necessary; API exists for all the events.

  The handler signature is:

    def handler_func(event, state)

  where:
    event:
      An Event object describing the event.

    state:
      An EventState object describing the current state.

  Use key_to_code() to convert from the name of a key to its code,
  and code_to_key() to convert a code to a name.

  The keys are listed in inevent.Constants.py or /usr/include/linux/input.h
  Note that the key names refer to a US keyboard.
  """
  def __init__(self, ioloop, cb, types = ["kbd", "mouse", "js"]):
    self.ioloop = ioloop
    self.cb = cb
    self.streams = []
    self.handler = EventHandler()
    self.types = types

    devs = list(find_devices(types))
    for index, type in devs:
      self.add_stream(index, type)

    self.udevCtx = pyudev.Context()
    self.udevMon = pyudev.Monitor.from_netlink(self.udevCtx)
    self.udevMon.filter_by(subsystem = 'input')
    self.udevMon.start()
    ioloop.add_handler(self.udevMon.fileno(), self.udev_handler, ioloop.READ)


  def process_udev_event(self):
    action, device = self.udevMon.receive_device()
    if device is None: return

    match = re.search(r"/dev/input/event([0-9]+)", str(device.device_node))
    devIndex = match and match.group(1)
    if not devIndex: return
    devIndex = int(devIndex)

    if action == 'add':
      for index, devType in find_devices(self.types):
        if index == devIndex:
          self.add_stream(devIndex, devType)
          break

    if action == 'remove':
      self.remove_stream(devIndex)


  def stream_handler(self, fd, events):
    for stream in self.streams:
      if stream.filehandle == fd:
        while True:
          event = stream.next()
          if event: self.handler.event(event, self.cb)
          else: break


  def udev_handler(self, fd, events):
    self.process_udev_event()


  def add_stream(self, devIndex, devType):
    try:
      stream = EventStream(devIndex, devType)
      self.streams.append(stream)

      self.ioloop.add_handler(stream.filehandle, self.stream_handler,
                              self.ioloop.READ)

      log.info('Added %s[%d]', devType, devIndex)

    except OSError as e:
      log.warning('Failed to add %s[%d]: %s', devType, devIndex, e)


  def remove_stream(self, devIndex):
    for stream in self.streams:
      if stream.devIndex == devIndex:
        self.streams.remove(stream)
        self.ioloop.remove_handler(stream.filehandle)
        stream.release()

        log.info('Removed %s[%d]', stream.devType, devIndex)


  def key_state(self, key):
    """
    Returns the state of the given key.

    The returned value will be 0 for key-up, or 1 for key-down. This method
    returns a key-held(2) as 1 to aid in using the returned value as a
    movement distance.

    This function accepts either the key code or the string name of the key.
    It would be more efficient to look-up and store the code of
    the key with KEY_CODE[], rather than using the string every time. (Which
    involves a dict look-up keyed with a string for every key_state call, every
    time around the loop.)

    Gamepad keys are:
      Select = BTN_BASE3, Start = BTN_BASE4
      L1 = BTN_TOP       R1 = BTN_BASE
      L2 = BTN_PINKIE    R2 = BTN_BASE2

    The action buttons are:
      BTN_THUMB
      BTN_TRIGGER
      BTN_TOP
      BTN_THUMB2

    Analogue Left Button = BTN_BASE5
    Analogue Right Button = BTN_BASE6

    Some of those may clash with extended mouse buttons, so if you are using
    both at once, you'll see some overlap.

    The direction pad is hat0 (see get_hat)
    """
    return self.handler.key_state(key_to_code(key))


  def clear_key(self, key):
    """
    Clears the state of the given key.

    Emulates a key-up, but does not call any handlers.
    """
    return self.handler.clear_key(key_to_code(key))


  def get_keys(self):
    return [code_to_key(k) for k in self.handler.get_keys()]


  def release(self):
    """
    Ungrabs all streams and closes all files.

    Only do this when you're finished with this object. You can't use it again.
    """
    for s in self.streams: s.release()